一、核心概念与场景总结
- setState 的同步 / 异步特性
setState 本身不是单纯的同步或异步 ,其执行时机由 React 的更新上下文决定:
-
异步场景(React 可控上下文):React 合成事件(onClick/onChange)、生命周期函数(componentDidMount 等)、React 批量更新机制触发时,setState 是 "异步" 的(实际是延迟执行 + 批量更新)。
-
同步场景(React 不可控上下文):原生事件(addEventListener)、setTimeout/setInterval、Promise.then/catch、手动调用 DOM 事件等,setState 是同步执行的。
示例代码:
js
import React, { useState, useEffect } from 'react';
const StateDemo = () => {
const [count, setCount] = useState(0);
// 1. React 合成事件(异步)
const handleReactClick = () => {
setCount(count + 1);
console.log('合成事件中:', count); // 输出旧值 0(异步未更新)
};
// 2. 生命周期等效逻辑(异步)+ 原生事件 / 定时器(同步)
useEffect(() => {
// 原生事件(同步)
const nativeBtn = document.getElementById('native-btn');
const handleNativeClick = () => {
setCount(prev => prev + 1);
console.log('原生事件中:', count); // 输出新值(同步更新)
};
nativeBtn.addEventListener('click', handleNativeClick);
// 3. setTimeout(同步)
setTimeout(() => {
setCount(prev => prev + 1);
console.log('setTimeout 中:', count); // 输出新值(同步更新)
}, 0);
// 4. useEffect 等效生命周期(异步)
setCount(count + 1);
console.log('useEffect 中:', count); // 输出旧值 0
// 解绑事件
return () => nativeBtn.removeEventListener('click', handleNativeClick);
}, []);
return (
<div>
<p>Count: {count}</p>
<button onClick={handleReactClick}>React 合成事件</button>
<button id="native-btn">原生事件</button>
</div>
);
};
export default StateDemo;
2. dispatchAction 更新链路(核心流程)
dispatchAction 是 React 状态更新的入口,完整链路如下:

关键源码片段(简版)
js
// 1. dispatchAction 入口(ReactFiberClassComponent.js)
function dispatchAction(fiber, queue, action) {
// 创建 Update 对象
const update = {
action,
lane: requestUpdateLane(fiber), // 优先级
next: null,
};
// 将 Update 加入队列
const pending = queue.pending;
if (pending === null) {
update.next = update;
} else {
update.next = pending.next;
pending.next = update;
}
queue.pending = update;
// 调度更新
scheduleUpdateOnFiber(fiber, update.lane);
}
// 2. 调度更新(ReactFiberWorkLoop.js)
function scheduleUpdateOnFiber(fiber, lane) {
// 标记更新优先级
markUpdateLaneFromFiberToRoot(fiber, lane);
// 判断是否批量更新(核心:batchedUpdates 标记)
if (isBatchingUpdates) {
// 批量更新:暂存更新,不立即执行
if (isUnbatchingUpdates) {
flushSyncCallbacks(); // 非批量模式下立即执行
}
return;
}
// 非批量更新:立即调度
const root = getRootForFiber(fiber);
scheduleCallback(lanesToEventPriority(lane), () => {
performSyncWorkOnRoot(root); // 执行同步更新
});
}
3. 批量更新原理
React 批量更新的核心是 事务 (Transaction) 和 isBatchingUpdates 标记:
- React 在执行合成事件、生命周期等逻辑时,会先将 isBatchingUpdates 设为 true,此时所有 setState 不会立即触发 DOM 更新,而是将更新请求加入队列;
- 当事件 / 生命周期执行完成后,React 会将 isBatchingUpdates 设为 false,然后批量处理队列中的所有更新,只触发一次 render 和 commit 阶段,减少 DOM 操作,提升性能。
手动开启 / 关闭批量更新示例
js
import React, { useState, useEffect } from 'react';
import { unstable_batchedUpdates } from 'react-dom';
const BatchDemo = () => {
const [count, setCount] = useState(0);
useEffect(() => {
// 手动开启批量更新
setTimeout(() => {
unstable_batchedUpdates(() => {
setCount(prev => prev + 1);
setCount(prev => prev + 1);
console.log('批量更新中:', count); // 输出旧值,最终只更新一次
});
}, 0);
}, []);
return <div>Count: {count}</div>;
};
export default BatchDemo;
知识点总结
一、setState 同步/异步场景总结
1. 异步场景(React 可控)
- React 合成事件(onClick、onChange、onSubmit 等)
- 组件生命周期函数(componentDidMount、componentDidUpdate 等)
- React 批量更新机制覆盖的场景(如 unstable_batchedUpdates 包裹)
- 特点:setState 延迟执行,多次调用合并为一次 DOM 更新,this.state 立即获取为旧值
2. 同步场景(React 不可控)
- 原生 DOM 事件(addEventListener 绑定的事件)
- 定时器(setTimeout、setInterval)
- 异步操作(Promise.then/catch、async/await)
- 手动触发的 DOM 事件(如 element.click())
- 特点:setState 立即执行,this.state 可立即获取新值
3. 注意事项
- setState 第二个参数(回调函数)始终能获取最新状态:this.setState({}, () => console.log(this.state.count))
- 函数式 setState 可避免状态依赖问题:this.setState(prev => ({ count: prev.count + 1 }))
二、总结
- setState 特性 :同步/异步由 React 上下文决定,核心是
isBatchingUpdates标记控制是否批量更新; - dispatchAction 链路:创建 Update → 加入队列 → 调度更新 → render 计算新状态 → commit 更新 DOM;
- 批量更新原理:React 通过事务机制将可控上下文的多次 setState 合并为一次 DOM 更新,提升性能。