返回
React setState 深度解析:解读源码,透视渲染机制
前端
2023-09-18 04:16:06
引子
React 中的 setState 函数,看似简单,却暗藏玄机。它的运作机制往往令人费解,特别是它的异步更新行为,经常让人丈二和尚摸不着头脑。本文将深入 React setState 源码,逐行剖析其内部实现,揭开它的神秘面纱。
setState 初探
setState 函数负责更新组件状态。它接受一个更新对象作为参数,合并到组件的当前状态中。乍一看,这似乎是个简单的过程,但实际上,它涉及到一连串复杂的异步操作。
源码剖析
要了解 setState 的运作机制,我们必须深入其源码。在 React 18 版本中,setState 函数位于 react-dom/cjs/react-dom.development.js 文件中,具体实现如下:
export function setState(inst, payload, callback) {
const partialState = typeof payload === 'function' ? payload(inst.state) : payload;
const prevState = inst.state || {};
const state = Object.assign({}, prevState, partialState);
inst.state = state;
// ... 省略其他代码
}
异步更新流程
从源码中可以看出,setState 并没有立即更新组件状态,而是将其存储在实例的 state 属性中,并触发一个异步更新流程。这个流程包含以下步骤:
- 调度更新: setState 调用会调度一个更新任务,将其添加到 React 的更新队列中。
- 批量更新: React 会将多个更新任务批量处理,以提高效率。在批量更新阶段,React 会遍历更新队列,并调用各个组件的 shouldComponentUpdate 方法。
- 状态更新: 如果 shouldComponentUpdate 返回 true,React 会调用组件的 render 方法,更新组件的虚拟 DOM。
- DOM 更新: React 会将更新后的虚拟 DOM 与上一次渲染的虚拟 DOM 进行对比,生成差异更新。然后,它会将差异更新应用到实际的 DOM,完成视图更新。
4 次 log 的解析
基于上述的异步更新流程,我们可以理解为什么 setState 调用会产生 4 次 log。这 4 次 log 对应着以下 4 个阶段:
- 第一次 log: setState 调用时,更新任务被调度,此时 log 为 0。
- 第二次 log: 批量更新阶段,组件的 shouldComponentUpdate 返回 true,log 为 0。
- 第三次 log: 组件的 render 方法被调用,此时状态已更新,log 为 2。
- 第四次 log: DOM 更新阶段,实际的 DOM 被更新,此时 log 为 3。
总结
React setState 函数的异步更新行为旨在优化性能,防止不必要的重新渲染。通过深入理解 setState 的源码和更新流程,开发者可以更好地优化组件性能,构建更高效的 React 应用。