React Functional Component Class Component

[React] Functional-component vs Class-component

許馨方 Mia Hsu 2022/10/12 16:13:33
1887

React 撰寫的部分分成了 Functional componentClass 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 必須在一開始被指向才可以使用,方法有兩種:
  1. 在 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. 生命週期

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 要做的事情。
許馨方 Mia Hsu