今天介紹的是 useMemo hook,透過它可以記憶一個值。
useMemo 真的是效能優化的利器?倒也不一定,看你怎麼使用它,過度使用反而只是拖垮效能罷了
由於當元件重新渲染時,擁有複雜計算的函式又會重複執行一次,為了避免函式又進行不必要的執行,所以透過 useMemo 將函式運算完的值存起來。像需要花比較多時間執行的複雜函式都適合使用 useMemo。
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useMemo(computation)
: 如果沒有加上這個陣列,每次都會重新執行函式去產生新的值useMemo(computation, [])
: 空陣列的話,回傳值不會改變useMemo(computation, [...someValues])
: 有加上一些元素值的話,當元素值改變時會重新更新函式回傳值You may rely on useMemo as a performance optimization, not as a semantic guarantee.
這裡示範一下用 useMemo 去包住 Math.random() 函式,所以除了第一次渲染之外,每次印出 memoizedValue 都會出現一樣的值。
import React, { useState, useMemo } from "react";
export default function App() {
const [count, setCount] = useState(0);
const memoizedValue = useMemo(() => {
return Math.random();
}, []);
console.log(memoizedValue);
return (
<p>
<button onClick={() => setCount(count + 1)}> Click </button>
</p>
);
}
在 React 官方文件有提到,我們可以使用 console.time
和 console.timeEnd
去得出產生某個值出現的時間。
例如有段經過特定條件過濾的陣列 visibleTodos,我們可以用 console.time
和 console.timeEnd
去計算產生該陣列花費的時間。
console.time('filter array');
const visibleTodos = filterTodos(todos, tab);
console.timeEnd('filter array');
然後我們再加上 useMemo 去記憶該 visibleTodos,第一次渲染時當然還是會去做 filter 的動作,但之後就可以減少不必要的計算,並以此去評估是否值得去做優化。
console.time('filter array');
const visibleTodos = useMemo(() => {
return filterTodos(todos, tab); // Skipped if todos and tab haven't changed
}, [todos, tab]);
console.timeEnd('filter array');