把“為什么用、怎么用、用錯了怎么辦”一次講透,附 React 19 自動優化前瞻。
一、useMemo 是什么?
一句話:
useMemo = 記住(緩存)昂貴計算結果,只在依賴變化時重新計算。
const memoValue = useMemo(() => {return heavyCompute(a, b);
}, [a, b]);
- 第 1 個參數:計算函數,必須返回一個值。
- 第 2 個參數:依賴數組,React 用
Object.is
比對。 - 返回值:緩存值,依賴不變就復用。
二、使用場景 3+1
場景 | 示例 | 收益 |
---|---|---|
昂貴計算 | 大數據過濾 / 排序 / 圖表計算 | 避免每次渲染重算 |
穩定引用 | 把對象/數組傳給子組件 | 配合 React.memo 減少子組件重渲染 |
函數緩存 | 返回函數時用 useCallback 語法糖 | 防止子組件 props 變化 |
React 19 之前 | 手動優化瓶頸 | React 19 編譯器將自動處理 |
三、實戰:Todo 列表性能優化
問題:每次添加 todo,都重新過濾 1000 條數據
function TodoList({ todos, filter }) {// ? 每次渲染都執行 filterTodosconst visibleTodos = filterTodos(todos, filter);return visibleTodos.map(todo => <li key={todo.id}>{todo.text}</li>);
}
解決:useMemo 緩存過濾結果
function TodoList({ todos, filter }) {const visibleTodos = useMemo(() => filterTodos(todos, filter),[todos, filter]);return visibleTodos.map(todo => <li key={todo.id}>{todo.text}</li>);
}
依賴
[todos, filter]
不變,filterTodos 只在依賴變化時運行。
四、常見誤區與對策
誤區 | 后果 | 對策 |
---|---|---|
依賴項漏寫 | 緩存值不更新 | 使用 ESLint react-hooks/exhaustive-deps |
過度使用 | 緩存成本 > 計算成本 | 先寫簡單代碼,后優化 |
返回函數 | 誤用 useMemo(() => fn) | 改用 useCallback(fn, deps) |
五、React 19 之后:還要手動用嗎?
React 19 編譯器 已能 自動記憶化:
- 大部分場景 無需手寫
useMemo
/useCallback
。- 僅在 第三方庫要求引用穩定 或 極端昂貴計算 時手動使用。
六、一鍵記憶化模板
import { useMemo } from 'react';export function useExpensiveValue<T>(factory: () => T, deps: any[]): T {return useMemo(factory, deps);
}// 用法
const data = useExpensiveValue(() => heavyCompute(a, b), [a, b]);
七、一句話總結
useMemo = “計算緩存”,只在依賴變化時重算;React 19 之前手動優化瓶頸,之后讓編譯器兜底。