两者都在渲染之间缓存某些内容,以便每次都不会重新计算/重新创建:
useMemo缓存一个计算值。useCallback缓存一个(它是 )。
useMemo(() => fn, deps)它们的存在是为了避免 (a) 重复执行昂贵的工作和 (b) 破坏 memoized 子组件所依赖的引用相等性。
function Table({ rows, onSelect }) {
// (a) expensive computation — recompute only when `rows` changes
const sorted = useMemo(() => rows.slice().sort(byName), [rows]);
// (b) stable function identity — so a React.memo child doesn't re-render,
// and effects depending on it don't re-fire
const handleSelect = useCallback(id => onSelect(id), [onSelect]);
return <Grid rows={sorted} onSelect={handleSelect} />;
}
没有 useCallback 的情况下,handleSelect 在每次渲染时都是全新的函数。React.memo(Grid) 会看到一个"新的" prop 并仍然重新渲染,从而破坏 memoization。对于传递给 memoized 子组件或在 useEffect 依赖数组中使用的对象也是一样。
const x = useMemo(() => a + b, [a, b]); // ❌ pointless — adding is cheaper than memoizing
useMemo/useCallback 会增加混乱,甚至可能更慢。(React 19 的编译器可以自动 memoize,减少了这种需要。)一个包含详细解答的 IT 面试题库——从初级到高级。
捐赠