React 是怎麼運作的
- React 是一個打造使用者介面的 JavaScript 函式庫
- React 負責管理元件資料狀態(props, state, context)透過 Virtual DOM 評估哪些元件需要被更新
- React Dom 是操作 Web 的介面,跟瀏覽器的 真實 DOM 互動
- React Dom 收到 React 的更新資訊(比較差異),操作瀏覽器 DOM 來改變畫面
- 比起直接操作真實 DOM,先從 Virtual DOM 評估差異再操作真實 DOM 裡必要修改的部分,較不耗資源
當 props, context, state 更新時會發生什麼事
- props, context 更新其實背後都是代表 state 更新,而 props 跟 context 只是傳輸資料管道不同
- React 會重新評估(re-evaluate),即執行元件裡的函式(包含子層元件),並更新資訊給 React DOM
- 下方範例,每次 props 變化(true false),父子元件都會重新 re-evaluate,true 時渲染 This is new,false 則沒有內容
|
|
父層重新渲染時,子層也會重新評估是否渲染
- 父層狀態有變但沒有傳入子層,父層渲染時子層也會重新評估,因為子層元件也是父層的程式碼一部分,但受影響的子層不一定會重新渲染
- 下方範例在真實 DOM 沒有變化(也沒有任何 flash),表示沒有重新渲染,但會看到 console.log 有跳出,表示有重新評估
|
|
React.memo 優化 Functional Component 效能
- 只有父層傳下來的 props 值有改變,才會重新渲染子層跟子層下的元件
- 下方範例若 props 沒改變,不會重新渲染 DemoOutput 跟 MyParagraph
- 使用 React.memo 也會耗費效能,適合不常更新的較高層級父層元件使用
|
|
- Button 不適合使用 React.memo,除了是比較低階元件之外
- onClick 指向同一個 function,雖然內容沒有變更,但函式是物件,所以每次 render 都會是新的地址,每次都會當作 props 有更新值
- 可以用 useCallback 來解決這個問題
|
|
useCallback 優化 Functional Component 效能
- 用 useCallback 包裹函式,第二個參數也是一個陣列
- 相依[]空陣列表示永遠不會改變,只會跑一次,若裡面有變數做條件判斷觸發,會因為 closure,變數不會更新
|
|
- 回到剛剛 button 的範例,記住按鈕裡面的onClick參數避免因為函式地址改變重新渲染按鈕
|
|
- 若 toggle 外面有一層判斷,相依參數需要加上 allowToggle
- 若為空陣列則函式本身永遠不會改變而無法觸發
|
|
每次的 state update 其實是非同步的排程
- 保證順序但不保證立即執行
- 會有 state batching 來優化渲染流程,同一個函式內程式執行完後再統一更新 state ,並判斷哪些元件需要重新渲染
|
|
|
|
useMemo 優化 Functional Component 效能
- 使用時機:遇到吃效能的運算例如 sort,會希望避免不必要的重新運算
- useMemo 包裹耗能的運算函式,把運算結果放在return後
- 相依參數放陣列裡面,可以用解構賦值把要相依的結果放入[]
|
|
- 需要在App.js傳入時就做useMemo固定住記憶體地址才有意義
|
|
- 不是每個都需要做useMemo,因為也會佔據記憶體,根據經驗跟狀況判斷是否需要使用