跳到主要内容

useMemo

面试速答(30 秒版 TL;DR)

  • useMemo(factory, deps) 用来缓存计算结果,依赖不变时复用上次结果。
  • 它适合:
    • 昂贵计算
    • 需要稳定对象/数组引用
    • 配合 memo / useEffect 避免引用抖动
  • 它不适合把所有变量都包一层“假装优化”。
  • 面试里一句话区分:useMemo 缓存值,useCallback 缓存函数。

1. 心智模型

组件每次 render,函数体里的表达式都会重新执行:

const visibleList = list.filter(item => item.visible)

如果:

  • 计算很重
  • 或这个结果要作为 props 传给子组件

那么每次都重算/重建引用,可能没有必要。

useMemo 的作用就是:依赖没变时,复用上次结果。

2. 基本用法

const visibleList = useMemo(() => {
return list.filter(item => item.visible)
}, [list])

它缓存的是 list.filter(...) 的结果,而不是这个函数本身。

3. 常见使用场景

3.1 昂贵计算

const result = useMemo(() => heavyCompute(data), [data])

3.2 稳定对象引用

const options = useMemo(() => ({
page,
pageSize,
}), [page, pageSize])

如果不缓存,这个对象每次 render 都是新引用。

3.3 配合 React.memo

父组件给子组件传数组或对象 props 时,经常需要 useMemo 稳定引用,否则子组件的浅比较会失效。

4. React 18 里该怎么理性使用

React 18 并不意味着所有计算都要 memo 化。

判断标准更应该是:

  • 这段计算真的重吗?
  • 这个引用稳定真的能减少额外工作吗?
  • 代码复杂度增加值不值得?

如果只是很轻的表达式,例如简单拼字符串,通常没必要。

5. 面试高频答法

Q1:useMemouseCallback 的区别?

  • useMemo 缓存结果
  • useCallback 缓存函数引用

Q2:useMemo 能保证不重算吗?

不能把它理解成强语义缓存。更稳的说法是:React 可能复用 memo 结果,但你不应该依赖它做语义正确性保证,它主要是性能优化提示。

Q3:为什么对象/数组经常配 useMemo

因为它们是引用类型。内容一样不代表引用一样,而很多浅比较就是按引用判断的。

常见追问

1)所有对象字面量都要 useMemo 吗?

不需要。只有当“引用稳定”这件事真的影响下游行为时才值得做。

2)它能解决闭包问题吗?

不能。闭包问题还是依赖和时机问题,不是 memo 本身能修好的。

易错点/坑

  • 轻微计算也无脑上 useMemo
  • useMemo 当成业务语义依赖,而不是性能优化。
  • 依赖漏写,导致缓存结果过期。

速记要点(可背诵)

  • useMemo:缓存计算结果。
  • 典型场景:昂贵计算、稳定对象/数组引用、配合 memo
  • 原则:只在“缓存结果真的有价值”时使用。