iT邦幫忙

2025 iThome 鐵人賽

DAY 19
0
Modern Web

30 天掌握 React & Next.js:從基礎到面試筆記系列 第 19

Day 19:function component vs Class component 的差異

  • 分享至 

  • xImage
  •  

本篇內容參考自 Overreacted 網站的 “How Are Function Components Different from Classes?”。

現在幾乎所有 React 新專案都用函式元件(Function Component),好像 class 元件逐漸被淘汰。但到底這兩者之間,真正的差別是什麼?
今天我們來聊聊 Overreacted 那篇文章提到的一個關鍵差異:函式元件的 closure 捕捉 vs class 的 this 可變性。

概念解釋

  • ** Class Component **:用 class 宣告,有 this.statethis.props,方法通常讀取 this 上的值。
  • ** Function Component + Hooks**:用函式寫,用 useStateuseEffect 等 Hook 管理狀態與副作用。

這篇 Overreacted 的觀點是:真正的差異在於 行為模型 (behavior model),特別是在 callback 或延遲執行時,函式元件的 closure 捕捉/class 的 this 更新方式的不同。

核心差異:Closure 捕捉 vs this 可變性

  • 在 Function component 裡,每一次 render,useEffect 裡的 callback function 都會被重新建立,而它會閉包捕捉當下的 state / props
    假如這個 callback 被延遲執行(如 setTimeout、事件裡),它會用當時被捕捉的值,即使後來 state / props 有變,也不會去拿最新的。

  • 在 Class component 裡,callback 通常用 this.statethis.props,而 this 是 mutable(可變的),會隨著每次 render 更新。
    所以 callback 被執行時,讀到的就是最新的 this.state / this.props

這就是兩者在「非同步 / 延遲行為」下會有不同行為的原因。

範例程式碼

Class 版本:

class Counter extends React.Component {
  state = { count: 0 };

  componentDidMount() {
    setTimeout(() => {
      console.log("class count:", this.state.count);
    }, 1000);
  }

  render() {
    return <button onClick={() => this.setState({ count: this.state.count + 1 })}>
      Count: {this.state.count}
    </button>;
  }
}
  • 假設你在 setTimeout 執行前按了一下按鈕,class 版本會在 log 裡拿到最新的 this.state.count

Function 版本:

function CounterFn() {
  const [count, setCount] = React.useState(0);

  React.useEffect(() => {
    setTimeout(() => {
      console.log("fn count:", count);
    }, 1000);
  }, [count]);

  return <button onClick={() => setCount(count + 1)}>
    Count: {count}
  </button>;
}
  • 在這個版本中,setTimeout 裡的 callback 捕捉到了那次 render 的 count。即便後來 count 更新,這個 callback 還是印出最初那次捕捉的數字。

常見誤區

  • 有人認為 Function component 不能有狀態/生命週期,其實可以靠 Hook。
  • 有人以為 class 一定比 function 效能好;在多數情況下效能差距不大,重點在 closure vs this 的邏輯差異。

小練習

寫一個 unction component,有一個按鈕點擊會 count +1,同時 setTimeout 在 2 秒後印出 count
問:印出什麼值?為什麼?怎麼改寫,才能印最新的 count

面試回答模板

在 React 中,Function component和 Class component 最大的差異在於它們如何取得 state 和 props。

  • Function component裡,callback 會「閉包(closure)」它定義當下那一次 render 的 state/props。
    所以如果這個 callback 被延遲執行(例如在 setTimeout、事件、或 Promise 之後才跑),它讀到的值可能是舊的(stale >value)。

  • Class component裡,callback 通常是透過 this.state / this.props 來存取。
    因為 this 永遠指向同一個實例,this.statethis.props 在每次更新後都會被 React 換成最新的,所以 >callback 幾乎總是能讀到最新的值。

Function components differ from class components mainly by how they capture state and props.
In function components, callbacks “closure” the state/props from the render in which they were defined, so delayed callbacks can see stale values.
In class components, callbacks refer to this.state / this.props, which always reflect the latest values.


上一篇
Day 18:Before You memo()
系列文
30 天掌握 React & Next.js:從基礎到面試筆記19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言