React 元件生命週期一次搞懂:從誕生到離開,它經歷了哪些階段?

更新日期: 2025 年 4 月 14 日

在你踏入 Hook 的世界之前,有一個觀念非常關鍵 —— 你要先了解 React 元件是怎麼「活著」的。

React 並不是畫面 render 一次就結束,它背後其實運行著一套「生命週期」的機制,幫助我們在適當的時機做適當的事情。

這篇文章,我們不談 Hook、不談函式型元件,只專注在 class 元件的生命週期(lifecycle)概念,幫助你建立 Hook 之前該有的背景知識。


🔰 前言:React 不是一次畫完就沒事了

很多剛接觸 React 的初學者,對元件的理解可能是這樣的:

「我寫了一個元件,它顯示出來了,這樣就完成了吧?」

乍看之下沒錯,但這樣的想法其實忽略了 React 的真正強大之處 —— 它是一個會隨著資料改變而自動更新的 UI 系統,而這也意味著:

👉 元件並不是靜態的 HTML,而是有「生命週期」的動態單位!


🎯 React 元件是一個「有生命」的存在

你可以把每個元件想像成一個在網頁上「出生、成長、最後消失」的小角色。

在這個過程中,你可能會想讓它做一些事情,例如:

  • 在元件「剛出現」的時候,向伺服器發送 API 請求,載入資料
  • 在元件「被更新」的時候,根據新的資料重新執行某些動畫
  • 在元件「即將消失」的時候,清除事件監聽器或中止計時器,避免記憶體外洩

這些事情,像是抓資料、加入事件監聽、開啟動畫效果,都不是隨便想寫在哪就能寫的

舉個例子:

React 每個元件都會有一個叫做 render() 的函式,負責「描述畫面要長什麼樣」。

你可以把它想成畫畫用的藍圖:它只是負責告訴 React 要畫什麼,不能真的在這裡「做事」。

所以如果你把像是抓資料、操作 DOM、設定計時器這些「動作」寫在 render() 裡,React 可能會報錯,或造成畫面反覆更新,甚至整個卡住。

✅ 簡單來說:render() 是畫畫用的地方,不是做事的地方。

那我們該把這些「該做的事」放在哪裡呢?

這時候就需要一個幫你規劃好「什麼時候該做什麼」的流程,讓元件在正確的時間點完成正確的事情。

這個流程就是我們接下來要介紹的重點:

🌀 元件生命週期(Component Lifecycle)

它就像劇本一樣,把一個元件從「出生 → 使用 → 結束」的每一個階段都規劃清楚,讓你知道:

  • 什麼時候可以初始化資料?
  • 什麼時候適合啟動動畫?
  • 什麼時候要清除資源、收拾善後?

React 元件生命週期是什麼?

當你在畫面上放入一個 React 元件,它其實就像是一個有「生命」的個體一樣,會經歷:

  1. 誕生(Mounting)
  2. 成長與改變(Updating)
  3. 死亡(Unmounting)

你可以想像這個元件就像一個演員,從走上舞台、演出過程中根據劇情改變表現,最後退場。整個過程就叫做「元件的生命週期(Component Lifecycle)」。

這是 React 幫你安排好的一套流程,讓你可以在對的時機點,做對的事。

Mounting(掛載)

當元件第一次出現在畫面上,會經歷這個階段。

你可以在這時:

  • 初始化資料
  • 抓 API 載入內容
  • 加入 DOM 事件監聽
  • 啟動動畫或計時器

簡單來說,這是元件第一次「出生」的時間點

Updating(更新)

當元件收到新的 props,或內部 state 改變時,就會重新渲染畫面。這就是更新階段。

你可以在這時:

  • 根據新資料更新畫面
  • 比較新舊值做條件處理(例如觸發動畫)
  • 做效能優化(例如決定要不要真的更新畫面)

這階段發生的頻率可能很高,因為 React 是個「會根據資料自動更新畫面」的框架。

Unmounting(卸載)

當元件要從畫面上消失(例如被條件隱藏或頁面切換)時,會進入卸載階段。

你可以在這時:

  • 移除計時器
  • 取消事件監聽
  • 中止未完成的 API 請求

這階段最重要的工作是「收尾」,避免記憶體洩漏或不必要的運算繼續存在


React 元件的三階段流程總覽

理解概念後,我們來看一下 class 元件在這三個階段中,實際會呼叫哪些生命週期方法(lifecycle methods):

✅ 小提醒:這些生命週期方法只在 class 元件中存在。你之後會學到,在函式元件中要靠 Hook 來實作這些能力。

生命週期是 React 的「舞台流程表」

你可以把這整個流程想成一場演出:

階段比喻對應方法你可以做的事
登場登台開場constructor + componentDidMount初始化 + 抓資料
表演中劇情發展、換裝render + componentDidUpdate更新畫面、觸發效果
退場下台收工componentWillUnmount停止計時器、清除資源

這套機制讓你的元件不只是畫面,而是一個有節奏、有邏輯的「行為單位」。

接下來,我們會逐一拆解這些階段可以做什麼,幫你掌握元件的完整生命流程。


各階段能做什麼?你該怎麼用?

在 React 的三大生命週期階段中,每一階段都有對應的函式(lifecycle methods),幫助你在「正確的時間點」執行「該做的事」。

這段會帶你逐步拆解每個階段可以使用的函式,以及適合處理的邏輯。

掛載階段(Mounting)

這是元件第一次被放進畫面(DOM)中的階段,常見函式如下:

函式說明
constructor()元件剛被建立,可以用來設定初始 state 或綁定方法
render()描述畫面內容(JSX),不可以做資料請求或副作用操作
componentDidMount()元件已經真正被渲染並掛載到 DOM,可以開始做事了

✅ 實務上你會在這階段做什麼?

  • 設定初始 state 或接收 props 資料
  • 發送第一次 API 請求、載入伺服器資料
  • 初始化動畫、設定計時器、加入事件監聽(例如 window.addEventListener

💡 小提醒:大部分初次載入的邏輯都寫在 componentDidMount 裡。

更新階段(Updating)

這個階段會在元件的 props 改變,或是 state 被更新時觸發。這些改變會導致元件重新 render,更新畫面。

函式說明
shouldComponentUpdate(nextProps, nextState)讓你決定是否需要更新畫面(回傳 true or false)
render()根據新的 props / state 更新畫面內容
componentDidUpdate(prevProps, prevState)畫面更新完成後可以執行的副作用邏輯

✅ 實務上你會在這階段做什麼?

  • 比較新舊 props / state 差異,執行條件邏輯
  • 根據更新結果啟動動畫或滾動效果
  • 執行 log 分析、API 上報或資料統計

💡 小提醒:

  • shouldComponentUpdate 是效能優化的好工具,能避免不必要的重新渲染。
  • componentDidUpdate 很適合用來「對比前後資料做出反應」,例如當某個值改變時觸發 API。

卸載階段(Unmounting)

當元件要從畫面上被移除,會觸發這個階段。

這時候你要記得「做收尾工作」,避免留下不必要的副作用或記憶體洩漏。

函式說明
componentWillUnmount()元件即將從畫面移除,是處理清理邏輯的唯一機會

✅ 實務上你會在這階段做什麼?

  • 清除計時器(clearInterval, clearTimeout
  • 移除事件監聽器(例如:window.removeEventListener
  • 取消訂閱(WebSocket、資料串流)
  • 終止未完成的 API 請求或動畫(避免報錯)

💡 小提醒:你可以把這裡想像成「元件下台收工,記得把舞台整理乾淨再走」。

額外補充說明

  • render() 是唯一會出現在「掛載階段」與「更新階段」的函式。
    它的唯一職責是:根據資料描述畫面要怎麼顯示(回傳 JSX)。不能寫副作用邏輯,也不會操作 DOM。
  • constructor()componentDidMount() 是你最常會用的初始化組合
    一個負責準備資料(像是設定 state),一個負責畫面出現後開始運作(例如 API 請求)。
  • componentWillUnmount() 是你避免「記憶體洩漏」的關鍵環節
    尤其是使用 WebSocket、setInterval、EventListener 等「持續作用」邏輯時,一定要清掉。

小結:在對的時機做對的事

階段建議行為
掛載設定初始資料、發送 API、加入監聽器
更新比較資料差異、觸發動畫、副作用處理
卸載清理資源、移除事件、停止任務

這些生命週期方法的設計,讓你可以不用擔心「什麼時候該做什麼」,而是按照 React 提供的節奏,把程式寫在正確的位置,讓元件更有條理、效能更好、bug 更少!


為什麼你要懂生命週期?

React 的元件不是一塊靜態 HTML,而是一個「會呼吸、會互動、會改變」的動態角色。

你寫的每一個元件,其實都是一個會隨著使用者行為和資料變化,不斷更新畫面的「活體程式碼」。

既然元件有生命,就不能亂寫!

你要懂它什麼時候出生、什麼時候會改變、什麼時候會消失,才能在對的時機對的事

常見錯誤情境與對應生命週期解法

❌ 錯誤 1:在 render() 裡抓資料

你可能會這樣寫:

render() {
  fetch('https://example.com/data') // ❌ 錯!
  return <div>內容</div>;
}

這樣做會導致什麼問題?

  • render() 是每次畫面更新都會被呼叫的地方
  • 每次更新都發送一次 API 請求,會重複抓資料爆炸
  • 此時 DOM 還沒出現在畫面上,有些操作會報錯

✅ 正確作法:把這種「一開始載入資料」的邏輯,寫在 componentDidMount() 裡:

componentDidMount() {
  fetch('https://example.com/data').then(...) // ✅ 正確
}

❌ 錯誤 2:API / 計時器一直跑,即使元件被移除

想像這個情境:

  • 你用 setInterval() 每 3 秒更新一次數據
  • 使用者切換頁面,但這個元件還在背景繼續跑

結果就是:記憶體還在被吃、效能變差,甚至可能引發錯誤

✅ 正確作法:把清除計時器的邏輯寫在 componentWillUnmount() 裡:

componentDidMount() {
  this.timer = setInterval(this.doSomething, 3000);
}

componentWillUnmount() {
  clearInterval(this.timer); // ✅ 元件離開前收拾乾淨
}

❌ 錯誤 3:每次更新都重做一樣的事情

你可能在 componentDidUpdate() 裡寫了這樣的邏輯:

componentDidUpdate() {
  this.doAnimation(); // ❌ 每次更新都做
}

但有時資料根本沒變,或不需要執行動畫,這樣不但浪費效能,還可能出現閃爍、邏輯錯誤。

✅ 正確作法:用 shouldComponentUpdate() 搭配條件判斷:

shouldComponentUpdate(nextProps, nextState) {
  return nextProps.value !== this.props.value; // ✅ 只有資料變了才更新
}

生命週期幫你做的三件事

了解元件生命週期,不只是背幾個函式名稱而已,而是幫助你「寫出健全的元件」的基礎功:

✅ 1. 管理效能

  • 避免不必要的重渲染
  • 控制資料更新的頻率
  • 提高整體應用程式的流暢度

✅ 2. 管理副作用(side effects)

  • 確保只有在需要時抓資料、操作動畫或 DOM
  • 讓你的元件乾淨、好預測、不亂跑

✅ 3. 控制元件行為

  • 掌握元件什麼時候該初始化、更新、清除
  • 確保每個元件都有「始、有終」,不留下遺毒(像計時器、記憶體洩漏)

💬 如果你曾經寫過畫面怪閃、資料抓不回來、記憶體爆掉的 React 程式碼——很有可能就是沒有正確使用元件生命週期!


✨ 五、小結:下一步是 Hook 的世界!

現在,你已經建立了 React 元件「從誕生到離開」的基本觀念:

  • React 元件不是寫完就結束,它是個活生生的東西
  • 每個階段都有對應的函式讓你可以加入自訂邏輯
  • 控制這些階段,就是掌握元件行為的關鍵

你可能會有以下疑問:

  • 「這套生命週期方法好複雜,為什麼要記這麼多 function?」
  • 「每個方法還只能做特定的事,邏輯要分來分去,好麻煩…」
  • 「如果能讓我用一種方式處理所有行為該多好!」

👉 所以 React 推出了全新的做法 —— Hooks!

Hook 可以讓你用函式型元件就做到相同甚至更強大的功能,還能更靈活地封裝邏輯、拆分模組。

下一篇文章,我們就要正式進入 Hook 的世界,帶你從 class 解放,輕鬆管理元件行為。

Similar Posts

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *