昨天我們介紹了什麼是 memorized hook,介紹他們是如何提升 React 的效能。接著,我們來更詳細一點的介紹各個 hook 要怎麼使用。
useMemo 是個可以避免不必要重複執行的 memorized hook。他會偵測傳入 hook 中的依賴參數,如果依賴參數沒有發生變化,則不會更新回傳值。基於這一點,他可以拿來做許多提升效能的工具。
這邊稍微再說明一下語法:
const returnValue = useMemo(()=> someHeavyFn(a, b), [a, b])
第一個參數要放入一個 callback function,其中放入要執行的複雜 function;第二個則要放入依賴參數,也就是要偵測有無變化的變數,需要放入一個 Array,跟過去介紹的 useEffect 相同,若 Array 中沒有放入任何值,則回傳值不會改變。
函數的回傳值是我們要執行的 function 執行後的值,可以直接用做元件內的資料或傳值。
useMemo 會在元件渲染時執行,要特別注意不要用 useMemo 做不會在渲染中執行的事,例如 side effect ,應交由渲染後執行的 useEffect 去做。
當元件被重新渲染時,有些 function 我們不需要重新執行,這些 function 可能耗時極長,有可能很吃效能,若每一次都執行將會大大拖累整個網站。
因此,這種 function 就可以使用 useMemo:
let a = 1, b = 2;
const heavyFunction = (a, b) => {
for(let i = 0; i < 1000000; i++){};
return a + b
}
const number = useMemo(() => heavyFunction(a, b), [a, b])
當父元件更新時,有時候子元件不見得也需要強制更新。這時候也可以使用 useMemo。
這個狀況下,一旦父元件被按鈕更新狀態,便會強制子元件也更新:
const Child = () => {
let counter = useRef(0);
const myFunction = () => {
counter.current++;
};
const value = myFunction();
return (
<div>
更新次數:{counter.current}
</div>
)
}
const Parent = () => {
const [pressCounter, setPressCounter] = useState(0);
return (
<div>
<Child />
<button onClick={()=> setPressCounter(pressCounter + 1)}>更新</button>
</div>
)
}
若是將 value = myFunction()
的部分加上 useMemo 來阻止重新執行的話,就可以避免元件也被重新渲染:
// 不使用依賴變數,保持不變
const value = useMemo(()=>myFunction(), [])
參考資料
useMemo - React
React 性能優化那件大事,使用 memo、useCallback、useMemo
React Hooks: 深入剖析 useMemo 和 useEffect
以上是比較常見的用法,主要就是避免 function 做不必要的執行。他的用法跟 useCallback 相似,但又有所不同,明天會再介紹 useCallback。