React中increaseCount方法的计数器为何未按预期累加至4?
为什么三者同时使用时计数器没有增加至4?
嘿,这个问题其实戳中了React中setState的几个核心特性,我来一步步给你拆解清楚:
先回顾三个setState的类型和单独/组合的表现
- X和Y是函数式更新:它们接收
prevState作为参数,每次更新都是基于上一次更新后的最新状态,所以两个一起用的时候,count从0→1→2,最终加2,这很好理解。 - Z是「对象式更新+回调」:单独用的时候,第一个对象式更新会把count从0→1,然后回调函数在这次更新完成后执行,此时
this.state.count已经是1,所以回调里的setState再把count变成2,最终也加2。
三者同时用的时候,问题出在哪?
核心原因是React的批量更新机制,以及对象式更新的「快照特性」:
1. 批量更新模式会收集所有setState请求
当你在React的合成事件(比如按钮点击事件)里调用increaseCount时,React会自动开启「批量更新模式」——所有的setState调用不会立即执行,而是先被收集到一个更新队列里,等当前函数执行完,再统一处理队列里的更新。
2. 对象式更新是基于调用时的state快照
Z里的第一个setState({ count: this.state.count + 1 })是对象式更新,这里的this.state.count是你调用setState那一刻的state值(也就是初始的0),这个值会被固定下来,不会随着队列里其他更新而变化。
3. 批量处理时的执行顺序和覆盖问题
当批量处理更新队列时:
- 先执行X和Y的函数式更新:count从0→1→2。
- 然后执行Z的第一个对象式更新:它会把count设置为
0+1=1,直接覆盖了之前X和Y带来的count=2的结果。 - 最后,批量更新完成,执行Z的回调函数:此时count已经是1,回调里的
setState把count变成2。
所以最终count只增加到了2,而不是预期的0+2+2=4。
怎么改才能让三者同时用的时候count增加到4?
把Z的第一个对象式更新改成函数式更新就行:
this.setState(prevState => ({ count: prevState.count + 1 }), function() { this.setState(prevState => ({ count: prevState.count + 1 })); });
这样所有的更新都是基于前一次的最新状态,批量处理时X→Y→Z第一个会把count从0→1→2→3,然后回调里的更新把count变成4,就能达到预期效果了。
内容的提问来源于stack exchange,提问作者DCR
相关产品推荐
相关产品推荐

