React
Functional Component
Class Component
[React] Functional-component vs Class-component
2022/10/12 16:13:33
0
2506
React 撰寫的部分分成了 Functional component 與 Class component 兩種。
Class component 是 React 原有的寫法,而Functional component 是 2019 年 v16.8 Hooks 釋出後的寫法。
目前官方推薦開發者使用 Functional component ,原因在於:
- 編譯快程式碼更少。
- 性能比起 Class Component 更好。
- 無狀態、沒有生命週期的 Component(使用 Hooks 取代)。
當然 Class component 並沒有被捨棄,還是可以在 React 中使用,它有以下幾種特性:
- 需要比較多 JS 的背景知識。
1. this 概念 怎麼 Call function 決定。
2. 需要有物件導向的知識
補充說明: [JS] 物件導向 JavaScript (object-oriented JavaScript)
- 具有生命週期。
- 需要在 Component 中設置狀態(state)。
- 不能使用 Hook。
了解兩者的差異後,我們可以直接從「渲染 JSX 方法、State、this 的影響、處理狀態方法、生命週期」這五個面向進行比較。
1. 渲染 JSX 方法
Functional component
- 用 function 去實作一個 Component。
- 可使用 ES6 箭頭函式。
- 直接將 function return 內容將渲染到畫面上。
export default function FunctionalComponent() { return <h1>FunctionalComponent</h1>;};
Class component
- 用 Class 去實作一個 Component。
- 需繼承 React.Component 類別。
- 需定義 render() 並將要渲染到畫面上的內容 return。
import { Component } from "react";export default class ClassComponent extends Component { render() { return <h1>ClassComponent</h1>; }}
2. State
Functional component
- 沒有 State 因此需使用 Hook 中 useState() 定義資料和改變資料方法。
import React, { useState } from 'react';const Example = () => { const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> );}
Class component
- State 是一個 JavaScript object 為 Component 「最新」資料。
- 需透過 constructor 初始化 State,需特別注意的是,不能使用點運算子改變 State 裡面的資料(會造成資料更新但畫面沒有重新 render 的情況),必須使用 setState() 設定裡面的資料 。
class Hello extends React.Component { constructor() { this.state = { name: "miaHsu", }; } render() { return ( <h1> Hello, {this.props.name} </h1> ); }}this.setState({name: 'BrainLin'});
3. this 的影響(傳遞 State 至 method)
Functional component
- this 會直接指向 component 本身,利用 function 閉包(Closure)的特性,藉由閉包實現封裝的功能,因此在 method 中可以直接取用變數。
function TodoFunctional() { const [value, setValue] = useState(""); const [errorMsg, setErrorMsg] = useState(""); const handleAddTodo = () => { if (value === "") { setErrorMsg("請輸入 Todo"); return; } }
Class component
- 需在一開始透過 constructor 初始化 props。
class TodoClass extends Component { constructor(props) { super(props); // 初始化 props }}
- this 必須在一開始被指向才可以使用,方法有兩種:
- 在 constructor 內綁定 this 指向。
class TodoClass extends Component { constructor(props) { super(props); this.handleInputChange = this.handleInputChange.bind(this); } handleInputChange(e) { this.setState({ value: e.target.value }); }}
2. 改成 classmethod 綁定 this 指向。(類似箭頭函式的寫法)
class TodoClass extends Component { constructor(props) { super(props); this.state = { value: "", };} handleInputChange = (e) => { this.setState({ value: e.target.value }); };}
4. this 的影響(傳遞 Props 至子元件)
Functional component
- 將 props 作為 function 參數傳遞。
Class component
- 需在父元件一開始透過 constructor 初始化 props,在子元件用 this.props 取出。
5. 生命週期
生命週期就是「 一個 Component 從 建立 ➡️ ️️ 更新 ➡️ 銷毀,所會經歷的各個階段 」
Functional component
由於 Functional component 只是一個單純的 function,因此是不存在生命週期的,不過我們可以透過各種 Hook 來監聽各階段的觸發時間點。
Class component(官網說明)
提供了三個方法(綠色的部分)調用
生命週期 methods 比對圖
這些方法在 Component 生命週期的各個點被調用。
寫法比較總表
實際做一個 Todo List!
- 想知道兩者的差異,直接實作最能理解,這邊提供已經做好的版本,大家可以把其中一個版本刪除重新撰寫看看。
- GitHub 連結
- 功能1:新增 todo、刪除 todo、改變狀態
- 功能2:將資料儲存於 LocalStorage
總結
Class component
- 透過 ES6 語法來實作物件導向的 class component。
- 由於 this 指向的關係,state 和 props 會拿到最新的結果(會改變),會較不易於進行 callback 操作。
- 提供許多 lifecycle method 使用,方便管理較複雜的 component 狀態。
- 與 functional component 相比,較難進行測試。
Functional component
- 目前主流寫法。
- 透過閉包的形式來管理狀態的 function component 。
- 把許多 method 都寫在 function 中,自己本身就像是 render function,較容易抽出共同邏輯,或是進行模組化測試。
- State 是以 useState 定義資料和改變資料狀態。
- 生命週期的方法,是以 useEffect 來決定 render 要做的事情。