跳到主要内容

使用useCallback做性能优化

面试速答

  • 以下内容以 React 18 为准。
  • useCallback 的本质不是“缓存函数逻辑”,而是 缓存函数引用
  • 它通常用于避免因为函数引用每次都变,导致子组件或 effect 无意义更新。

什么时候有价值

1. 配合 React.memo

const Child = React.memo(function Child({onSave}: {onSave: () => void}) {
return <button onClick={onSave}>保存</button>
})

const onSave = useCallback(() => {
submit(form)
}, [form])

如果父组件每次 render 都创建新函数,子组件浅比较可能失效。

2. 作为 Hook 依赖

某些自定义 Hook 或 effect 依赖某个回调时,稳定引用能减少无意义重建。

什么时候没必要

1. 子组件本来就会重渲染

如果子组件不做任何记忆化,父组件刷新后它本来就会重新执行,这时单独稳定回调意义不大。

2. 回调本身很简单,且没有向下传递压力

为了一个很轻的函数强加 useCallback,只会让依赖关系更复杂。

useCallbackuseMemo 的关系

可以把它理解成:

useCallback(fn, deps)

约等于:

useMemo(() => fn, deps)

一个缓存“结果”,一个缓存“函数引用”。

React 18 下的成熟答法

不要把 useCallback 说成“性能银弹”。更稳的表达是:

当函数引用稳定性会影响子组件记忆化、Hook 依赖或订阅重建时,useCallback 才真正有价值。

标准答法

问:useCallback 主要优化什么?

答:优化的是函数引用稳定性,避免把“父组件每次 render 都创建新函数”传播成下游无意义更新或副作用重建。

易错点

  • 误以为 useCallback 能减少函数创建成本本身。
  • 不看场景全量套用。
  • 依赖写不全导致回调拿旧值。

速记要点

  • useCallback 缓存函数引用,不缓存执行结果。
  • 典型场景:React.memo 子组件、Hook 依赖。
  • 没有引用稳定诉求时,不必强上。