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:useMemo 和 useCallback 的区别?
useMemo缓存结果useCallback缓存函数引用
Q2:useMemo 能保证不重算吗?
不能把它理解成强语义缓存。更稳的说法是:React 可能复用 memo 结果,但你不应该依赖它做语义正确性保证,它主要是性能优化提示。
Q3:为什么对象/数组经常配 useMemo?
因为它们是引用类型。内容一样不代表引用一样,而很多浅比较就是按引用判断的。
常见追问
1)所有对象字面量都要 useMemo 吗?
不需要。只有当“引用稳定”这件事真的影响下游行为时才值得做。
2)它能解决闭包问题吗?
不能。闭包问题还是依赖和时机问题,不是 memo 本身能修好的。
易错点/坑
- 轻微计算也无脑上
useMemo。 - 把
useMemo当成业务语义依赖,而不是性能优化。 - 依赖漏写,导致缓存结果过期。
速记要点(可背诵)
useMemo:缓存计算结果。- 典型场景:昂贵计算、稳定对象/数组引用、配合
memo。 - 原则:只在“缓存结果真的有价值”时使用。