学 React 有两条路:一条是只学 API,遇到问题查文档;另一条是先弄懂它的更新机制,然后大部分「奇怪行为」都变成理所当然。
这个专题走第二条。它的价值不在于让你能背出 Fiber 的架构图,而在于把原理和你每天写的代码对应起来——为什么列表的 key 不能用索引、为什么 setState 之后立刻读 state 拿到的是旧值、为什么给每个函数都套 useCallback 反而更慢。这些问题的答案都在下面三层机制里。
学习路径
第一层:虚拟 DOM。 React 不直接操作真实 DOM,而是先生成一棵 JS 对象树,和上次的树比对,只把差异应用到真实 DOM。先理解这个缓冲层的存在,以及它的代价——虚拟 DOM 不是「更快」,而是「在提供声明式写法的前提下,性能不至于太差」。
第二层:diff 算法。 逐棵树完整比对的复杂度是 O(n³),不可用。React 靠三个假设把它降到 O(n):只比同层、类型不同直接重建、同层用 key 标识身份。key 不能用数组索引,根源就在第三条——索引会在增删时错位,导致 React 认错节点,进而出现状态串位和无谓重渲染。
第三层:Fiber。 React 核心算法的重写,目的是把渲染工作切成小块、分散到多帧执行,让高优先级的交互不被长任务阻塞。理解了增量渲染,就能理解为什么 React 的更新是「可中断」的。
第四层:落到日常 API。 生命周期与 Hooks、setState 的批量合并、状态管理选型、组件复用的三代方案(HOC → render props → Hooks)。
三代组件复用方案对比
| 方案 | 复用什么 | 主要问题 | 现状 |
|---|---|---|---|
| Mixin | 任意成员 | 命名冲突、来源不明 | 已废弃 |
| 高阶组件 HOC | 组件逻辑 | 嵌套地狱、props 来源难追踪 | 少量场景仍适用 |
| Render Props | 组件逻辑 | 回调嵌套、JSX 结构变形 | 被 Hooks 大量替代 |
| 自定义 Hook | 状态逻辑 | 有使用规则约束 | 当前首选 |
常见误区
以为虚拟 DOM 比直接操作 DOM 快。 不是。手写的精准 DOM 操作一定比虚拟 DOM 快。虚拟 DOM 的价值是让你用声明式的方式写 UI,同时性能保持在可接受范围内——它买的是可维护性,付的是性能。
列表 key 用数组索引。 只要列表会增删或排序,索引就会错位。React 会把「第 2 项」当成同一个节点复用,导致输入框内容跟着串位。用数据里稳定的 id。
以为 setState 是异步的。 更准确的说法是「批量合并的」。React 会把同一事件循环内的多次调用合并成一次渲染,所以调用后立刻读 state 拿到的是旧值。需要基于前值计算时,传函数而不是传对象。
给每个函数都包 useCallback。 useCallback 本身有成本(创建依赖数组、每次渲染做比较)。只有在「这个函数会作为 props 传给被 memo 包裹的子组件」或者「它是某个 effect 的依赖」时才有收益。无脑包裹只会增加复杂度和依赖项填错的风险。
项目一开始就上状态管理库。 先用 useState 加 Context,等到确实出现「多个远距离组件共享同一份可变状态」时再引入。提前引入 Redux 这类方案,收益没见到,样板代码先写了一堆。
本专题全部文章
- React 状态管理选型,2024年我的建议React 状态管理选型:Redux、MobX、Context、Zustand 各自适合什么场景。先回答「什么时候才真需要状态管理库」,再按项目规模与团队情况给具体建议,不推销单一方案。
- useCallback 和 useMemo 我之前一直用错了useCallback 与 useMemo 正确用法:这两个 Hook 极易被滥用。讲清它们各自缓存什么、什么情况下才真正有收益,以及无脑包裹反而带来的复杂度与依赖项 bug。
- React 类组件和函数组件区别React 类组件与函数组件的区别:写法、state 与生命周期的实现方式、this 指向、性能表现与心智模型上的差异,以及两者共同遵守的「不可修改自身 props」约束。
- React 父子组件交互生命周期执行顺序React 父子组件生命周期执行顺序:挂载、更新、卸载三个阶段父子钩子的交错顺序完整梳理,帮你判断某段逻辑该放在父组件还是子组件的哪个钩子里。
- React render propsReact Render Props 详解:用一个值为函数的 prop 在组件间共享代码的技术,它的实现方式、与高阶组件的取舍,以及在 Hooks 出现后的适用场景。
- React setState 深入:批量合并、异步表现与同步时机React setState 深入:为什么它表现得像异步、批量更新的合并规则、传函数与传对象的差异,以及在生命周期和原生事件回调中行为为何不同。
- React Refs 详解:访问 DOM 节点与向父组件暴露引用React Refs 详解:在典型数据流之外访问 DOM 节点或组件实例的方式,createRef 与 useRef 的用法、回调 ref、forwardRef 转发,以及什么时候不该用 ref。
- React Fiber 架构:增量渲染如何解决页面卡顿React Fiber 详解:核心算法的重写,目标是让渲染工作可切分成块并分散到多帧执行(增量渲染),从而改善动画、布局与手势场景下的响应性。
- React 虚拟 DomReact 虚拟 DOM 详解:在数据与真实 DOM 之间加一层缓冲,通过新旧虚拟 DOM 比对只把变化部分更新到真实 DOM,这就是 React 性能表现的来源与它的实际代价。
- React Diff 算法React Diff 算法与性能优化:传统 diff 的 O(n³) 复杂度问题,React 如何用同层比较、类型判断、key 标识三个策略把它降到 O(n),以及据此写出高性能列表的方法。
- React Hook 使用指南:两条规则与 useState、useEffect 实战React Hook 入门:Hook 是 React 16.8 的新增特性,让你不写 class 也能用 state 和其他 React 特性。讲清什么时候该用 Hook、以及它解决了类组件的哪些问题。
- React Hooks 全解:数据驱动、副作用与 React 18 新增 HookReact Hooks 详解:useState、useEffect、useRef、useContext、useReducer 等核心 Hook 的用法与执行时机,以及 Hooks 的使用规则和背后的实现约束。
- React 组件生命周期详解:新旧钩子对比与四个阶段React 组件生命周期详解:挂载、更新、卸载三个阶段各自会执行哪些方法、每个钩子适合做什么,以及 React 16 之后废弃的几个钩子和它们的替代方案。
- React 高阶组件 HOC:属性代理与反向继承两种实现React 高阶组件(HOC)详解:什么是高阶组件、怎么用它复用组件逻辑、属性代理与反向继承两种实现方式,以及 HOC 的命名约定和使用时的注意事项。




