React15 架構可以分爲兩層:
React15 及以前,Reconciler 採用遞歸的方式創建虛擬 DOM,遞歸過程是不能中斷的。如果component tree層級很深,遞歸會佔用線程很多時間,遞歸更新時間超過了 16ms,用戶交互就會卡頓。
而爲了解決這個問題,React16 將遞歸的無法中斷的更新重構爲異步的可中斷更新,同時也因為遞歸的虛擬 DOM 數據結構無法滿足整體架構,藉此使得全新的 Fiber 架構應運而生
爲了解決同步更新長時間佔用線程導致頁面卡頓的問題,也爲了探索運行時優化的更多可能,React 開始重構並一直持續至今。重構的目標是實現 Concurrent Mode(併發模式)。
從 v15 到 v16,React 團隊花了兩年時間將源碼架構中的 Stack Reconciler 重構爲 Fiber Reconciler。
React16 架構可以分爲三層:
React16 的 expirationTimes 模型只能區分是否>=expirationTimes決定節點是否更新。
React17 的 lanes 模型可以選定一個更新區間,並且動態的向區間中增減優先級,可以處理更細粒度的更新。
Lanes 用二進制位表示任務的優先級,方便優先級的計算(位運算),不同優先級佔用不同位置的 “賽道”,而且存在批的概念,優先級越低,“賽道” 越多。高優先級打斷低優先級,新建的任務需要賦予什麼優先級等問題都是 Lane 所要解決的問題。
Concurrent Mode 的目的是實現一套可中斷 / 恢復的更新機制。其由兩部分組成:
concurrent(並行)功能部份
startTransition()
useTransition(): 類似於節流閥(Throttling)與防抖動(debouncing)的機制,但由 React 來控管更新的時間點
useDeferredValue(): 與 useTransition 類似機制,但用於從父母元件接收新值(useTransition 用於事件處理器觸發更新)
註: 更多相關內容可參考New feature: startTransition與New in 18: useDeferredValue
針對函式庫開發者部份
useId(): "不是"用來產生列表項目的 key,之前名稱為 useOpaqueIdentifier,目的是能同時在客戶端與伺服器端產生唯一 ID,避免伺服器端渲染(SSR)的事件處理器水合作用匹配上的問題。
useSyncExternalStore(): 主要針對外部狀態函式庫開發使用,如 redux, mobx, zustand 等等
useInsertionEffect(): 主要針對給 css-in-js 函式庫開發使用。(應用開發建議優先使用 useEffect 或 useLayoutEffect)