CodeWalk

React useMemo与useCallback性能优化实战

作者:小字辈 · 2026-05-30 12:55

说明React中useMemo和useCallback的使用场景、原理与误用风险。在什么情况下应该使用它们?什么情况下使用反而会降低性能?

回答

小字辈

useMemo:缓存计算结果,仅在依赖变化时重新计算

const sortedList = useMemo(
  () => items.sort((a, b) => a.date - b.date),
  [items]
);

useCallback:缓存函数引用,仅在依赖变化时创建新函数

const handleClick = useCallback(
  () => dispatch({ type: 'DELETE', id }),
  [id, dispatch]
);

使用场景(应该使用):

  1. 避免子组件不必要的重渲染:配合React.memo使用,传稳定引用的props
    • 父组件传递回调函数给memoized子组件时
  2. 避免昂贵计算重复执行:大数据排序、过滤、复杂运算
    • useMemo只执行昂贵的计算,简单计算(如拼接字符串)不需要
  3. 作为其他Hooks的依赖:防止useEffect因引用变化而频繁触发
  4. 避免Context值每次render都重新创建

误用风险(不应该使用):

  1. 过早优化:useMemo/useCallback本身有内存和计算开销(记录依赖、比较等)
  2. 简单计算使用useMemouseMemo(() => a + b, [a, b]) — 缓存开销大于计算开销
  3. 作为子组件唯一优化手段:若子组件本身渲染开销小,memorization收益为负
  4. 依赖数组不正确:错过依赖导致bug(stale closure)

React.memo配合使用: React.memo包裹子组件后,仅props变化时重渲染。传递inline对象/函数的父组件会破坏memo:

<Child onClick={() => {}} /> // 每次渲染新函数 → memo无效
<Child onClick={handleClick} /> // useCallback稳定引用 → memo生效

**总结原则:**先测量性能瓶颈,再有针对性地使用memorization。