useMemo 和 useCallback 的区别?什么时候该用?

区别

// useMemo:缓存值
const sortedData = useMemo(() => {
  return data.sort((a, b) => a - b)
}, [data])

// useCallback:缓存函数
const handleClick = useCallback(() => {
  console.log(id)
}, [id])

// useCallback 本质是 useMemo 的语法糖
const handleClick = useMemo(() => () => {
  console.log(id)
}, [id])

什么时候用

useMemo 适用场景:

  1. 昂贵的计算
const result = useMemo(() => {
  return heavyComputation(data) // 计算耗时 > 1ms
}, [data])
  1. 稳定引用对象(作为其他 Hook 的依赖或子组件的 prop)
const config = useMemo(() => ({ endpoint: '/api', timeout: 5000 }), [])

useCallback 适用场景:

  1. 传递给被 React.memo 包裹的子组件
const Child = React.memo(({ onClick }) => {
  console.log('Child render')
  return <button onClick={onClick}>Click</button>
})

function Parent() {
  const [count, setCount] = useState(0)
  // ✅ 使用 useCallback,count 变化时 Child 不会重新渲染
  const handleClick = useCallback(() => {
    console.log('clicked')
  }, [])
  return <Child onClick={handleClick} />
}
  1. 作为 useEffect 的依赖
const fetchData = useCallback(() => {
  api.get(id)
}, [id])

useEffect(() => {
  fetchData()
}, [fetchData])

什么时候不用

// ❌ 简单计算不需要 useMemo
const doubled = useMemo(() => count * 2, [count])
// 直接写就行
const doubled = count * 2

// ❌ 不传递给子组件的函数不需要 useCallback
const handleLocalClick = useCallback(() => { ... }, [])
// 直接定义即可
const handleLocalClick = () => { ... }

性能权衡

React 19 变化

React 19 编译器(React Compiler)可以自动优化 memo,未来可能不需要手动使用 useMemo/useCallback。

同分类其他题目