當有一個元件包含了複雜的計算,為了避免元件在每一次重新渲染時都會在重複執行這個複雜的函數,因此我們可以使用useMemo
記住函數回傳的值,等到useMemo
第二個參數 dependencies array 中的值有變動,函數才會重新渲染
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
在這個例子中:computeExpensiveValue(a, b)
是一個函數
useMemo 接受兩個參數:
第一個參數是一個函數,這個函數會返回一個計算的值,在這個基本語法例子中,它是 () => computeExpensiveValue(a, b)
。
第二個參數是一個陣列,是dependencies array,在這個例子中代表只有當 a 或 b 的值發生變化時,useMemo 才會重新計算 memoizedValue,如果 [a, b] 沒有變化, memoizedValue 會保持不變,即使元件重新渲染,這樣可以避免不必要的計算並優化元件的性能
在這個範例中,useMemo 用來存儲 computedValue 的結果,dependencies array則是[number]
代表 complexCompute 函數只有在 number 改變時被調用,其他情況下 computedValue 會被重用。
const complexCompute = (num) => {
// 假設這是一個複雜的計算
return num * num;
};
const ComputeComponent = () => {
const [number, setNumber] = useState(0);
const computedValue = useMemo(() => {
return complexCompute(number);
}, [number]);
return (
...
)
下方範例中建立一個長度是10000的array,使用useMemo來儲存filteredData
的值,只有當query
有改變時,filteredData
才會重新被計算,這樣的方式有助於提高性能,因為不需要在每次渲染時都重新過濾數據
const data = Array(10000).fill().map((_, i) => i);
const ExpensiveComponent = () => {
const [query, setQuery] = useState('');
const filteredData = useMemo(() => {
return data.filter(item => item.toString().includes(query));
}, [query]);
return (
...
)
最後React官方提到,不應該在任何地方都使用useMemo,確保只要在有要效能優化的地方即可,否則會讓 React 處理更多事情,造成不必要的的負擔。
參考文章
useMemo
Day8-React Hook 篇-認識 useMemo
React 性能優化那件大事,使用 memo、useCallback、useMemo