前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库React.memo 跳过重渲染 浅比较
ReReact性能与并发

React.memo 在什么条件下能跳过子组件渲染?

父组件执行了,并不意味着每个子组件都必须重新计算;先确认更新来自哪里,再判断 memo 是否有机会复用结果。

前端进阶之旅 · 一题精讲更新于 2026.09.06
React#性能与并发#React 性能#性能优化#并发编程
先看核心答案读代码示例
理解线索

判断 memo 是否有机会生效的三步

  1. 组件身份位置、类型和 key 对应同一实例,才能比较先前 props
  2. 输入比较默认逐项比较 prop 值,不是递归比较对象内部字段
  3. 更新来源父级带来的相同 props 可复用,自身更新另行处理

这里讨论手写 memo 的行为;React Compiler 的自动优化需要实际启用编译器,升级 React 版本不会自动启用它。

核心回答

先记住这个答案

memo 为组件建立一个基于 props 的优化边界。对于同一个位置、相同类型和 key 的组件,父级重新渲染时,默认比较每个 prop 的新旧值,全部通过 Object.is 比较才有机会跳过这次子组件渲染。它不会拦截组件自身状态更新或所消费的 Context 更新,也不会保留被卸载组件的实例。React 把它定义为性能优化,因此代码必须在不依赖跳过渲染的情况下仍然正确。

  • 默认逐个 prop 使用 Object.is 比较
  • 先保住组件身份,再讨论跳过渲染
  • 本地状态与 Context 有独立的更新来源

浅比较比较的是每一项输入

如果上次和本次都是 name 等于小林、score 等于八十分,两个基本类型输入保持相等,即使父组件生成了新的 JSX,memo 仍有机会复用成绩卡。这里没有要求父组件传入的整个 props 容器是同一个对象。

如果 score 换成一个新建的对象,即便内部数字没变,Object.is 比较也不相等。不要把浅比较描述成只比较第一层字段的业务内容;对于对象这一项,它判断的是引用身份,而不是自动展开字段。

把无关计数与真正的成绩变化分开

下面将成绩卡定义在模块顶层,父级计数只影响外面的 output。增加计数不改变成绩卡输入,增加成绩则改变 score。验证时应该分别观察这两条路径,并检查修改成绩后界面仍能及时更新。

可以在开发工具中记录子组件提交,也可以在测试夹具里加入提交阶段探针。不要把渲染函数中的日志次数直接解释成用户看见的提交次数;开发严格模式和未提交的渲染尝试都会干扰这种推断。

无关父状态与有效子输入TSX
import { memo, useState } from 'react';

const ScoreCard = memo(function ScoreCard({ score }: { score: number }) {
  return <p>小林的成绩:{score}</p>;
});

export default function ScoreDemo() {
  const [revision, setRevision] = useState(0);
  const [score, setScore] = useState(80);
  return <>
    <button onClick={() => setRevision(n => n + 1)}>增加父计数</button>
    <output>父计数:{revision}</output>
    <button onClick={() => setScore(n => n + 1)}>增加成绩</button>
    <ScoreCard score={score} />
  </>;
}

成绩卡只接收成绩,所以父计数变化提供了相同 props 的对照。示例没有把 memo 放在父函数内部,否则每次得到新的组件类型可能导致重新挂载,讨论浅比较就失去了前提。

哪些更新不会被这个边界挡住

在成绩卡内部增加展开状态,点击展开仍会触发它自己的更新。成绩卡读取主题 Context 时,提供者的新值也能使它更新。这些情况与父级重复传递相同成绩是不同路径,不能据此判断 memo 实现失效。

改变 key、切换组件类型或先移除再添加,会建立新的实例,之前的比较结果与局部状态都不能跨卸载继承。对需要长期保存的数据应另选合适的状态所有者,不能让 memo 承担持久化职责。

回答前,多想一步

容易答错的地方

把相同 props 说成绝不执行
React 允许在优化之外重新渲染组件,严格模式也会检查渲染纯度。如果组件只有在某次执行被跳过时才不会重复扣款或写日志系统,应把这些行为移到明确的事件或副作用生命周期中。
在父组件内部临时创建 memo 组件
在每轮父函数执行中调用 memo 并把结果当成子类型,会不断制造新的组件类型。应把组件声明移到模块作用域,先验证状态和焦点不会因为重新挂载丢失,再评估缓存收益。
试着用自己的话回答

面试官还会怎么问?

传递同一个对象但修改字段会怎样?

对象引用仍然相同,浅比较可能跳过需要发生的更新,界面因而陈旧。这是可变输入破坏了比较前提,修复办法是不可变地生成新对象,而不是要求 memo 检查已被覆盖的旧字段。

普通函数组件能自动获得这种优化吗?

需要区分运行时的普通父子更新和实际启用的 React Compiler。编译器可以生成自动缓存,但它不是仅靠安装 React 就开启的;面试或排查时应明确项目是否经过编译器转换。

如何证明这次优化值得保留?

选取真实的父级高频操作,在相同数据与环境下比较子树工作量和交互耗时。一次简单计数只能说明跳过条件,不能证明生产设备上的性能收益,更不能替代对慢计算或长列表的定位。

从一道题,走向一组知识

把知识连起来

性能与并发

给 memo 子组件传内联对象或函数为什么会失去优化机会?

进一步检查对象和回调引用为何破坏 props 比较。

状态共享

React memo 能阻止 Context 更新传给深层消费者吗?

区分 Context 通知与父级重复传递 props 的更新。

性能与并发

什么情况下 React.memo 没有收益,甚至增加成本?

用实际开销判断是否值得为这个边界维护缓存。

参考资料

  • React 官方:memo

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 浅比较比较的是每一项输入
  3. 把无关计数与真正的成绩变化分开
  4. 哪些更新不会被这个边界挡住
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑