useMemo vs useCallback
useMemo vs useCallback
一句话:useMemo 缓存 「函数的返回值」,useCallback 缓存 「函数本身」。两者都靠依赖数组决定要不要重算。
实际上 useCallback(fn, deps)完全等价于useMemo(() => fn, deps)——后者是前者的语法糖。 这句能答出来会加分。
| 缓存什么 | 什么时候用 | |
|---|---|---|
useMemo | 计算结果(值 / 对象 / 数组) | ① 计算真的贵(大列表排序过滤) ② 结果要当 props 传给 memo 组件 ③ 结果要当别的 hook 的依赖 |
useCallback | 函数引用 | ① 函数要传给 memo 组件 ② 函数是 useEffect 的依赖 ③ 自定义 hook 对外暴露的函数 |
什么时候不该用(这半边很多人答不出):两者本身都有成本—— 要存旧值、要比较依赖。 给一个 a + b 包useMemo 是纯亏。「先测量,再优化」; 默认不加,profiler 显示有问题再加。
最常见的误用:包了 useCallback但依赖数组里放了每次都变的东西 —— 等于没包,还多付了比较成本。
会追问:「React 19 的编译器会怎样?」—— React Compiler 能自动插入记忆化,大部分手写的useMemo /useCallback 将不再必要。 知道这个趋势会显得你在跟进。
In one line: useMemo caches “what a function returns”, useCallback caches “the function itself”. Both use the dependency array to decide whether to recompute.
In fact useCallback(fn, deps) is exactly the same thing as useMemo(() => fn, deps) — the former is sugar for the latter. Saying this scores points.
| What it caches | When to use it | |
|---|---|---|
useMemo | A computed result (value / object / array) | ① the work is genuinely expensive (sorting or filtering a big list) ② the result goes to a memo component as a prop ③ the result is a dependency of another hook |
useCallback | A function reference | ① the function goes to a memo component ② the function is a dependency of useEffect③ the function is part of a custom hook’s public API |
When not to use them — most people miss this half: both cost something — the old value is kept and the dependencies get compared. Wrapping a + b in useMemo is a pure loss. “Measure first, then optimise”: leave them out by default and add them when the profiler says so.
The most common misuse: wrapping something in useCallback but putting a value that changes every render in the dependency array — the cache never hits, and you paid for the comparison on top.
Follow-up: “What changes with the React 19 compiler?” — React Compiler can insert memoisation for you, so most hand-written useMemo and useCallback will stop being necessary. Knowing the direction shows you are keeping up.