React 17中setState回调为何仅第一个同步执行?
为什么React 17中setState的函数式更新回调看起来是同步执行的?
首先要明确核心区别:你传给setTest的函数式更新回调((e) => {...})本身是同步执行的,React所说的“setState是异步”,指的是state的最终更新和组件重新渲染是异步批量处理的,而非这个回调函数的执行时机。
你的代码执行顺序拆解
当点击按钮触发onClick回调时,代码会按以下顺序执行:
- 第一个
setTest调用:React立即同步执行传入的函数式回调,输出first 0,返回新state值1。此时React不会立刻更新组件的test变量,而是把这个更新操作加入内部的更新队列。 - 执行
console.log("inside1"),输出inside1。 - 第二个
setTest调用:React同样立即同步执行传入的回调,此时回调接收的e是前一个更新返回的1(函数式更新会自动获取队列中最新的state值),输出second 1,返回新state值2,这个更新也被加入队列。 - 当
onClick回调执行完毕后,React会批量处理队列中的所有更新,将test的值最终设置为2,然后触发组件重新渲染,此时组件顶部的console.log("HEYY STATE", test)会输出HEYY STATE 2。
为什么你觉得只有第一个回调是同步的?
你可能混淆了“函数式更新回调的执行”和“state更新的生效时机”:
- 所有函数式更新的回调都是同步执行的,第二个回调的执行在
inside1之后,完全是因为代码的书写顺序(第二个setTest调用在console.log("inside1")之后),而非异步。 - React的异步特性体现在:即使你执行了多次
setTest,组件的test变量不会立刻更新,直到React完成批量更新并触发重新渲染。
补充说明
在React 17中,合成事件(比如onClick)内的setState会被自动批量处理,这也是为什么两次setTest的更新会合并成一次重新渲染,而不是触发两次渲染。如果是在原生事件或者定时器回调中调用setState,React 17不会进行批量处理,此时每次setState都会触发一次渲染,但函数式更新的回调依然是同步执行的。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

