既然setState不返回Promise,为何await在该场景下生效?
为什么React中使用await调用setState的箭头函数后,状态会立即更新?
先看这段示例代码:
state = { x: false }; x = () => { this.setState({ x: true }); }; y = async () => { await this.x(); console.log(this.state.x); // 使用await时输出true,移除await则输出false }; y();
我们都知道React的setState是异步的,正常情况下调用setState后立即访问this.state会拿到更新前的值,所以移除await时输出false完全符合预期。但加上await后却输出true,这背后的核心原因和React的批量更新机制直接相关。
核心逻辑:React的批量更新策略
React会根据setState的调用上下文,决定是否批量处理状态更新:
- 批量更新场景:在React合成事件(比如按钮点击事件)、组件生命周期函数中调用
setState时,React会把多个setState调用合并成一次更新,此时setState是异步的,你无法在调用后立即拿到更新后的状态。 - 非批量更新场景:在原生JS事件、
setTimeout、Promise回调、async/await的异步代码块中调用setState时,React的批量更新机制会失效,此时setState会同步更新状态,你可以立即拿到更新后的值。
结合代码拆解两种情况的执行流程
情况1:移除await时
- 调用
y(),进入函数后直接执行this.x(),此时处于普通函数调用栈中,属于React批量更新的覆盖场景。 this.x()内部调用setState,React不会立即更新状态,而是把这个更新任务加入等待队列。- 紧接着执行
console.log(this.state.x),此时状态还没被更新,所以输出false。 - 函数执行完毕后,React才会批量处理队列中的状态更新,把
state.x改为true。
情况2:加上await时
- 调用
y(),进入async函数后执行await this.x()。 this.x()执行时,虽然调用setState的位置看起来是普通函数,但外层是async函数,后续代码会进入Promise的回调队列,此时React会判定当前处于非批量更新场景。setState被同步执行,state.x立刻变为true。this.x()返回undefined,await会等待这个值(相当于await Promise.resolve(undefined)),之后执行console.log(this.state.x),此时状态已经更新,所以输出true。
额外补充
这里要注意:this.x()本身并没有返回Promise,await只是等待一个undefined,真正导致状态同步更新的原因是**async函数的上下文触发了React的非批量更新逻辑**,而非await直接等待setState完成。
内容的提问来源于stack exchange,提问作者Patrickkx
相关产品推荐
相关产品推荐

