React 畫面更新的流程機制:reconcilliation
在 component 畫面管理機制中, component 的渲染機制可以分成兩個階段,分別是 render phase 和 commit phase。
Render phase
在 Render 階段,component 會進行渲染,並且產生 react element。
Commit phase
在 Commit 階段,component 會把產生的 react element 畫面結構提交並處理到實際的瀏覽器 DOM 上面。
第一次 render component
Render phase
- 執行 component function 產生以 props 和 state 描述 component 畫面的 react element。
- 接著將生成的 react element 交到 Commit phase 處理。
Commit phase
- mount: 這時由於是第一次 render,因此瀏覽器中並沒有 component 相對應的 DOM element,因此會將 react element 全部轉成相對應的實際 DOM element。
- mounted:
使用瀏覽器的 DOM API
appendChild()
將生成的 DOM element 掛載到實際的瀏覽器。
re-render component
Render phase
- 執行 component function 以新版本的 props 和 state 產生描述 component 畫面的 react element。
- 將新版本所產生的 react element 與上一次 render 的舊版 react element 進行樹狀結構的比較,找出差異。
- 將差異的部分交到 Commit phase 處理。
Commit phase
- 只操作新舊 react element 差異所對應的 DOM element。
React reconciliation
當呼叫 setState
後會發起 component re-render,React 會啟動 reconciliation 流程,最終更新瀏覽器的 DOM 並反映在畫面上。這個過程分為兩個主要階段:Render phase 和 Commit phase。component 內的子孫 component 也會連帶觸發 re-render:
-
呼叫
setState
更新資料 當呼叫setState
時,React 並不會立即更新狀態。setState
是一個非同步操作,React 會將這個狀態更新加入一個任務隊列中,並且會自動將多個setState
操作合併進行批次更新(batch update)。 -
檢查 state 是否有變化 React 會執行 Object.is(),檢查 state 新舊資料是否有變化。
- 如果沒有變化,代表資料沒有更新也就不需要更新畫面,接下來的流程就會中斷。
- 如果有變化,就是資料有更新,接著就會進行 re-render。
Render phase
- 重新執行 Component function re-render 會執行 component function 並以新版本的 props 和 state 產生新的 react element。
- Diffing 接著,react 會將前一份產生的舊版 react element 與新版 react element 使用 diffing 演算法來找出樹狀結構差異之處。
Commit phase
- 更新 DOM 比較完成後,根據差異的的部分所對應的 DOM element 進行操作, 這個更新過程會在瀏覽器的主執行緒上進行,包括更新 DOM 樹和應用 CSS 樣式,最後更新到瀏覽器 DOM 上。
Object.is()
拿掉會影響 reconciliation 嗎?
並不會,Object.is()
就只是個讓效能優化、減少 re-render 的檢查機制,沒有使用 Object.is()
檢查 state 就是直接讓 component 直接進行 re-render。