当 React 说“重新渲染”时,它意味着三件事
当你调用 setState 时,React 不仅仅是更新 DOM。它会按顺序运行三个独立的阶段。大多数开发者都会混淆这些阶段。理解其中的区别有助于你解决性能问题。
三个阶段:
• Render(渲染):React 调用你的组件函数。 • Reconcile(协调):React 将新的输出与旧的输出进行比较。 • Commit(提交):React 将更改应用于 DOM。
- Render 阶段
React 运行你的函数。它使用当前的 props。函数返回 JSX。这些 JSX 仅仅是一组 JavaScript 对象。人们称之为虚拟 DOM(virtual DOM)。它不是真实的 DOM,而是对 UI 应该是什么样子的描述。此时屏幕上还没有任何变化。这个阶段纯粹是数学和逻辑运算。
- Reconcile 阶段
React 持有旧树和新树。它会寻找它们之间的差异。如果元素类型发生了变化,React 会替换整个树。如果只是 props 发生了变化,React 则会更新它们。这就是 key 发挥作用的地方。key 帮助 React 通过标识符(identity)而不是位置来匹配列表中的项。这个阶段会生成一份更新 DOM 所需的最少步骤列表。
- Commit 阶段
React 获取更改列表并操作真实的 DOM。它会创建新节点并移除旧节点。这时用户才能在屏幕上看到变化。之后,浏览器会进行重绘(paint)。然后,useEffect 开始运行。
常见误区:
• 重新渲染并不总是会改变 DOM。如果输出结果相同,React 在 commit 阶段不会执行任何操作。
• React.memo 跳过的是函数调用,而不是跳过 DOM 更新。
• Props 本身并不触发重新渲染。父组件的重新渲染会触发子组件。Props 的变化只是其结果。
如何修复性能:
如果你的函数运行缓慢,说明你遇到了 Render 问题。请将繁重的工作移出函数,或者使用记忆化(memoization)。
如果 React 在重建巨大的列表,说明你遇到了 Reconcile 问题。请检查你的 key。
如果 DOM 更新过于频繁,说明你遇到了 Commit 问题。请使用虚拟化技术或改变你的结构。
React 19 和 React Compiler 现在已经为你处理了大部分这类工作。但了解这些阶段有助于你更好地进行调试。
