# React 效能優化 - React.memo / ReactMemo / useCallBack 比較應用 ###### tags: `React` ## `component` 會 re-render 的時機 1. state 改變 2. prop 改變 → React 提供了不同工具來協助判斷是否需要 re-render,來達到效能優化的目的。 # React.memo **→ 使用對象:`子 component` , do it in `子 component`** **→ 作用:避免 `props` 未改變,卻造成的不必要渲染** **→ 使用時機:`props` 不會一直改變的 `子 component`** ```jsx // prop type = string React.memo(myComponent) // prop type = object // 需要加入第二參數:function areEqual 來判斷兩個 props 是否一樣 React.memo(Component, **[areEqual(prevProps, nextProps)]**); ``` 避免不必要的渲染,透過 React.memo 包住子元件,它會記錄之前的 props 內容,只有當記憶中的 **props** 改變時(但 state、context 不變)才會重新渲染元件。 ### 特性 - shallow compare → 比較的是記憶體位置 (by reference) - 父元件重新渲染時,重新提供新的 props 給子元件,如果是 **`obj`** 型別的話,即使內容的值完全一樣,但還是會導致 memo 失效,重新渲染子元件 → 解法:傳入第二參數(用 **`function`** 來判斷這個**`obj props`**是否一樣) - **經常變更不一樣的 props 不建議使用 memo**(因為使用 memo 也是需要消耗記憶效能,所以要評估元件的大小是否值得使用。) # **useMemo** “你已經知道要花一個小時算出來的數學題的答案是什麼了,為何還要重算” **→ 使用對象:(很貴的)`function` 運算完的值, anywhere** **→ 作用:避免 `props` 未改變,卻造成的不必要渲染** ```jsx const memoizedValue = useMemo( () => computeExpensiveValue(a, b), [a, b]) //第一個參數傳入要記住的運算函式,第二個參數傳入 dependency array。 ``` # **useCallback** **→ 使用對象:`function` , in 父元件** **→ 作用:透過記憶 `function` 的記憶體位置,來避免子物件的重新渲染** → **使用時機: `function` 在父元件中被當作 `prop` 傳入子元件時(子元件搭配 `React.memo`)** ```jsx const memoizedCallback = useCallback( () => { doSomething(a, b); }, [a, b], ); ``` 將要記住記憶體位置的 **`function`** 用 `useCallback`包住並傳入 dependency array 當作第二個參數。 因為每一次 re-render 時 function 都會分配到一個新的記憶體位址,useCallback 可以記憶住該 function 的記憶體位置,避免每一次子元件 re-render 時都因為 function 的記憶體位置改變導致子元件重新渲染。 ### 使用時機: - 通常都是在 **function 被當作 prop 傳入子元件時** - 為了避免耗時的重新渲染,所以**在父元件就會用 `useCallback` 來包住 `function`** 並且傳入 dependency array 來判斷是否重新創建 function,並且同時搭配 **`React.memo`** 包住子元件,來讓在 function 不變時,子元件可以避免重新渲染。 RF: [[筆記] React.memo / useMemo / useCallback](https://xiaoming.coderbridge.io/2021/02/17/%E7%AD%86%E8%A8%98-reactmemo---usecallback---usememo/) [React 性能優化那件大事,使用 memo、useCallback、useMemo](https://medium.com/%E6%89%8B%E5%AF%AB%E7%AD%86%E8%A8%98/react-optimize-performance-using-memo-usecallback-usememo-a76b6b272df3)