前言
在刚接触React时,我们开发用的最多的hook之一就是useState,使用它的返回值setState去更新数据时,就会发现,在有些情况下,数据并不是像预期中更新了,获取到的数据还是旧的数据。这就是为什么说setState是异步的。
但是这里初学者就有疑问了,怎么异步编程范畴里没有提到setState呢?你理解的异步真的是对的吗?
经历了React各个版本的更新,setState异步机制有什么变化呢?
入门篇
setState的使用
大家都知道setState接受一个参数,这个参数是newState值。这里再补充一些其它知识。
setState其实可以接收两个参数:
import React, { useState } from 'react'; const [state, setState] = useState(initState); setState(newState, callback); 复制代码
- newState:最新值
- callback:异步更新之后的回调函数,即会在state更新之后执行
Tips: useState接收的initState是初始值,只会在mount时生效一次
为什么 setState 设计为异步?
import React, { useState } from 'react'; const [state, setState] = useState(false); const changeState = ()=>{ setState(true); console.log(state); // 此处打印结果显示是:false,而不是true,表明这里setState是异步的 } 复制代码
针对这个问题,Dan在github上给出了回答:why is setState asynchronous?
这里给出总结:
- 保持一致性。如果同步更新了setState,但还未执行render函数,那么state和props无法保持一致性,从而引发很多问题。
- 批量更新,提升性能。
如果获取到setState异步更新之后的值?
1.利用setState第二个参数,callback
// setState第二个参数是一个回调函数,会在state更新后执行 this.setState({ massage: "你好" }, () => { console.log(this.state.message); }); 复制代码
2.componentDidUpdate 生命周期函数
进阶篇
异步的定义
在入门篇提到,setState是异步的,但这个异步不同于EventLoop里说的异步。
我们常说的Promise.then()、setTimeout是异步执行,然而setState从js执行上来说它是同步执行的。这里setState的异步是指调用setState之后state能否立即更新(即表现出来是异步的,本质是同步的)。
简而言之:setState是同步执行,异步更新
setState一定是异步的吗?
先说结论:
legacy
模式下:在原生DOM事件和异步代码中,setState是同步的;在组件生命周期和React合成事件里,setState是异步的
concurrent
模式下:都是异步
legacy 模式
和 concurrent 模式
傻傻分不清楚
legacy 模式
是目前的主流模式,如今React18正式版已经发布,也就是说concurrent
(并发)模式已经不再处于试验中,concurrent
(并发)模式正式启用。
ReactDOM.render(<App />, rootNode) // 通过这个方式创建应用,为 legacy 模式 复制代码
ReactDOM.unstable_createRoot(rootNode).render(<App />) // 通过这个方式创建应用,为 concurrent 模式 复制代码
基于legacy
模式
在React的setState函数实现中,会根据一个变量isBatchingUpdates判断是直接更新this.state还是放到队列中回头再说,而isBatchingUpdates默认是false,也就表示setState会同步更新this.state,但是,有一个函数batchedUpdates,这个函数会把isBatchingUpdates修改为true,而当React在调用事件处理函数之前就会调用这个batchedUpdates,造成的后果,就是由React控制的事件处理过程setState不会同步更新this.state**。
基于concurrent
模式
React18正式版已经发布,concurrent
(并发)模式正式启用。在这个模式下,setState都是异步的。
相关链接:
React 中 setState 什么时候是同步的,什么时候是异步的?