React 中 setState 的执行机制是什么?
分析 React 组件调用 setState 时触发的状态更新、虚拟 DOM 计算和真实 DOM 更新的过程。
调用 setState()
时会触发以下过程:
- 状态更新请求:
setState()
是一个 异步请求,并非立即更新状态。React 会将新状态合并到当前状态队列中,并执行 批量更新优化(将多次连续调用合并为单次更新)。setState()
的第一个参数可以是:- 对象(例如
this.setState({ count: 1 })
):浅合并(shallow merge)到当前状态。 - 函数(例如
this.setState((prevState) => ({ count: prevState.count + 1 }))
):用于解决状态依赖问题(如连续递增)。
- 对象(例如
- 触发调和过程(Reconciliation):
- React 创建新的 虚拟 DOM 树(基于新状态),并启动 Diffing 算法 计算新旧虚拟 DOM 树的差异节点。
- 更新 DOM:
- 在 提交阶段(Commit Phase),React 将差异应用到 真实 DOM(仅更新变化的节点)。
- 回调与生命周期:
- 若提供第二个 回调参数(例如
this.setState({ ... }, callback)
),会在更新并重新渲染后执行(相当于在componentDidUpdate
后运行)。 - 类组件中会触发生命周期:
shouldComponentUpdate
(验证是否更新)render()
(生成新树)
→componentDidUpdate
(更新完成)
- 若提供第二个 回调参数(例如
代码示例:
this.setState(prevState => ({
count: prevState.count + 1 // 函数形式避免状态依赖问题
}), () => {
console.log("新状态值:", this.state.count); // 回调函数获取更新后的值
});
关键原理总结:
- 异步性与批量处理:避免频繁更新降低性能。
- 虚拟 DOM 更新策略:仅改变必要的真实 DOM(最小化操作成本)。
- 状态覆盖规则:对象形式浅层合并,函数形式可顺序操作依赖数据。