React.memo

React 中基于 props 比较跳过子组件重复渲染的组件级优化方式。

#tech / dev / frame #resource / react #type / concept #status / growing

[!info] related notes

React.memo

React.memo 是组件级优化工具。它的作用是:当 props 没变时,允许 React 跳过这个子组件的重复渲染。

一句话定义

如果一个子组件在相同 props 下总是产出相同结果,React.memo 可以帮助它减少不必要的重复执行。

它解决什么问题

  • 父组件重渲染时,某些纯展示子组件其实没必要跟着反复执行
  • 某些列表项或重组件渲染代价较高

它和 useMemo / useCallback 的关系

  • React.memo 作用在组件层
  • useMemo 作用在值层
  • useCallback 作用在函数引用层

很多时候,React.memo 是否生效,又会受到传给子组件的对象、数组、函数引用是否稳定的影响。

为什么对象 props 经常让它失效

React.memo 的问题往往不在“组件写错了”,而在“父组件每次都造出了新引用”。

<Child config={{ size: 'small' }} />

即使内容看起来一样,这里的对象身份每次都不同,比较结果通常也会被当成“变了”。

什么时候值得用

  • 子组件比较重
  • 父组件重渲染频繁
  • 组件确实经常收到相同 props

什么时候不值得用

  • 组件本身很轻
  • props 几乎每次都会变
  • 为了“做优化”而让代码变复杂

最短记忆方式

React.memo 跳过的是“相同 props 下的重复组件执行”,不是所有渲染问题的万能药。

面试要点

来自 react-memo-use-memo-use-callback-interview-question 的面试视角整理。

补充来自 react-memo-when-to-use-interview-question

一句话回答

只有当一个子组件本身渲染代价不低、父组件又经常重渲染、并且这个子组件经常收到相同 props 时,React.memo 才更可能带来实际收益。

最稳的回答主线

  • 组件轻不轻
  • props 稳不稳定
  • 父组件重渲染频不频繁
  • 为了生效,传入的对象和函数引用往往也要稳定

一个更完整的面试表达

可以这样答:

React.memo 不是默认必加的优化。只有当一个子组件本身渲染代价不低、父组件又经常重渲染、并且这个子组件经常收到相同 props 时,它才更可能带来收益。
如果组件很轻,或者 props 每次都在变,那即使包了 React.memo,实际效果也可能很有限。

一个典型例子

const ListItem = React.memo(function ListItem({ item, onSelect }) {
  return <button onClick={() => onSelect(item.id)}>{item.name}</button>
})

如果这里的 onSelectitem 在多数情况下都稳定,React.memo 就更有可能帮你跳过无意义的重复执行。

为什么它经常“加了没效果”

因为很多人会同时传这种 props:

<Child config={{ size: 'small' }} onClick={() => doSomething(id)} />

对象和函数每次都会是新引用,React.memo 就很难真正生效。

一个更工程化的判断

是否值得用 React.memo,通常要同时满足:

  • 子组件确实不轻
  • 父组件确实常 rerender
  • props 大部分时间稳定
  • 经过 profiling 或实际观察确认有收益

最短记忆方式

React.memo 不是默认必加项,它要看子组件重不重、props 稳不稳、父组件刷不刷。

一句话回答

React.memo 缓存的是组件渲染结果边界,useMemo 缓存的是计算结果,useCallback 缓存的是函数引用。

最稳的回答主线

React.memo

  • 用在组件层
  • props 没变时可跳过组件重复渲染

useMemo

  • 用在值层
  • 适合缓存昂贵计算结果

useCallback

  • 用在函数引用层
  • 适合需要稳定函数引用的场景

一个更完整的面试表达

可以这样答:

三者都和“缓存”有关,但缓存的对象不同。React.memo 是组件级边界优化,尽量在 props 没变时跳过子组件重复执行;useMemo 缓存的是某个计算结果;useCallback 缓存的是函数引用。
所以它们虽然经常一起出现,但职责不是一回事。

一个最容易加分的补充

很多时候它们会配合使用:

  • 父组件用 useMemo 稳定对象 props
  • 父组件用 useCallback 稳定函数 props
  • 子组件用 React.memo 才更有机会真正跳过 rerender

一个典型例子

const handleClick = useCallback(() => {
  doSomething(id)
}, [id])

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

return <Child onClick={handleClick} options={options} />

如果 Child 本身用了 React.memo,这条链路才更完整。

面试里最容易加分的一句

这三者都不是默认必加项,只有当它们真的减少了昂贵且无意义的工作时,才算有效优化。

常见误区

到处加 useCallback

如果函数引用变化没有产生实际问题,这样做只会增加复杂度。

useMemo 当成“任何值都要缓存”

只有昂贵计算才有明显收益。

最短记忆方式

memo 缓组件,useMemo 缓值,useCallback 缓函数。

创建于 2026/3/19 更新于 2026/5/27