iT邦幫忙

2026 iThome 鐵人賽

DAY 22
0
JavaScript

React 觀念架構:從js 基礎到Hook 底層邏輯 系列 第 22 篇

Day 22 Render 階段與 Commit 階段:Reconciler 與 Renderer 如何協作?

  • 分享至 

  • xImage
  •  

今天我們要深入拆解 React 的兩個核心處理階段——Render 階段(計算) 與 Commit 階段(渲染),並看看 Reconciler(協調器) 與 Renderer(渲染器) 是如何分工協作的。

一、 核心分工:Reconciler vs. Renderer

React 採用了模組化的架構設計,將「計算差異」與「繪製 DOM」徹底解耦:

  • Reconciler(如 react-reconciler):

    • 負責維護 WorkLoop、處理 Hooks、執行 Diffing 演算法,並構建 Fiber 樹。

    • 特點:純 JavaScript 運算,平台無關(Platform-agnostic)。

  • Renderer(如 react-dom / react-native):

    • 負責將 Reconciler 計算好的變更實際寫入目標平台的 UI 上(如瀏覽器 DOM 或原生 iOS/Android View)。

    • 特點:平台相關(Platform-specific)。

二、 Render 階段(可中斷的背景計算)

Render 階段的核心任務是:遞迴走訪 Fiber 樹,計算出哪裡發生變更,並在 Fiber 節點上記錄 Side Effect 標記(flags / subtreeFlags)。

這個階段包含兩個關鍵動作:

[HostRoot]
       /       ▲
  beginWork   completeWork
     /           \
  [Child] ──► [Sibling]
  1. beginWork(current, workInProgress, renderLanes)

    • 向下走訪:從根節點一路往下找尋變更的節點。

    • 主要任務:執行組件函數、比對 Props 與 State、處理 Hooks、呼叫 reconcileChildren(執行 Diffing 演算法),並為需要更新的 Fiber 節點打上 flags(如 Placement 插入、Update 更新、Deletion 刪除)。

  2. completeWork(current, workInProgress, renderLanes)

    • 向上回溯:當節點沒有子節點時,呼叫 completeWork 並向上回溯。

    • 主要任務:建立 DOM 實例(stateNode)、處理屬性賦值(如 className、onClick),並將子節點的 flags 向上收集冒泡到父節點的 subtreeFlags。

三、 Commit 階段(不可中斷的真實 UI 寫入)

當 workInProgress 樹在 Render 階段完全走訪完畢後,React 會進入 Commit 階段。這個階段是同步且不可中斷的,因為畫面更新必須一次到位,避免使用者看到半成品的 UI。

Commit 階段可以拆解為三大子子階段 (Sub-phases):

┌─────────────────────────────────────────────────────────────┐
│ 1. Before Mutation 階段:在操作 DOM 前(如執行 getSnapshotBeforeUpdate)│
├─────────────────────────────────────────────────────────────┤
│ 2. Mutation 階段:真正操作 DOM(根據 flags 進行 插入/更新/刪除)     │
├─────────────────────────────────────────────────────────────┤
│ 3. Layout 階段:DOM 已寫入(執行 useLayoutEffect、更新 ref)      │
└─────────────────────────────────────────────────────────────┘
  * 切換根節點 current 指針 (current = workInProgress)
  * 畫面上線後非同步呼叫 useEffect

三大子階段詳細解析:

  1. Before Mutation 階段:

    • 遍歷 Effect 鏈表,觸發 Class Component 的 getSnapshotBeforeUpdate。

    • 準備調度非同步的 useEffect。

  2. Mutation 階段(最關鍵):

    • Renderer 開始登場!根據 Fiber 上標記的 flags,真正呼叫 appendChild、removeChild 或 setAttribute 修改真實 DOM。

    • 執行舊組件的 useEffect Cleanup 函數。

  3. Layout 階段:

    • 在此時刻,根節點 pointer 正式切換(current = workInProgress)。

    • 同步執行 useLayoutEffect 的 Callback。

    • 綁定與更新 useRef 的 current 屬性。

Commit 階段完成後,主線程交還給瀏覽器進行排版與繪製(Reflow / Repaint)。隨後,React 會非同步觸發 useEffect 的設定函數。

四、 useLayoutEffect vs useEffect 的源碼級差異

理解了 Render/Commit 階段後,這兩個 Hook 的根本差異就一目了然了:
https://ithelp.ithome.com.tw/upload/images/20261006/20178516mtFck4HbyL.png


上一篇
Day 21 Fiber 雙緩衝機制與 WorkLoop:React 如何調度優先級?
系列文
React 觀念架構:從js 基礎到Hook 底層邏輯 共 22 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言