一、在同步环境中异步,在异步环境中同步。
setState本身并不具备绝对的同步/异步概念。
比如:在promise的then()方法中、setTimeOut()、setInterVal(),ajax的回调等异步环境中,setState就是异步的。
react会有一个上下文环境,在同步环境中,setState处于react的上下文中,react会监控动作合并,所以setState()是异步的。而在异步环境中,react实际上已经脱离了react的上下文环境。所以setState()是同步执行的。
代码如下(示例):setState()的同步和异步的案例
const [state,setState] = useState(0); //初始化为 0
setState(1); //当前处于同步环境,所以setState是异步的
console.log(state); //此时因为setState是异步的,state还未被赋值 打印结果是 0
setTimeOut(() => {
//当前处于异步环境,所以setState()是同步的
setState(5);
console.log(state); //打印结果是5
},0)
setState()在react中一开始之所以被设定为异步触发,是因为每当触发setState时react需要去更新视图。
通过异步更新视图来合并在短时间内的大量setState动作。
这样,当我们在短时间内多次的调用setState时,视图只会被更新一次。
代码如下(示例):setState()同步环境中异步执行 --合并动作案例
const [state,setState] = useState(0);
//快速给state赋值,连续赋值五次
for(let i =0;i<5;++i){
setState(i);
}
//实际上,因为setState动作合并的特性,视图只会被更新一次而不是五次
以上案例中,虽然setState被赋值了五次,但,视图不会更新五次。因为动作合并的原因,视图只会更新一次,也就等于只执行了setState(4);
但是!!
这是setState在同步环境中触发异步更新机制的时候。
如果是在异步环境中呢?
我们看看案例。
代码如下(示例):setState()异步环境中同步执行 --不合并请求案例
const [state,setState] = useState(0);
//快速给state赋值,连续赋值五次
Promise.resolve().then(() => {
//当前处于异步环境。setStat同步进行
for(let i =0;i<5;++i){
setState(i);
}
})
//在这次案例中,上面setState货真价实的被赋值了5次。视图也真真切切的被更新了五次
上面案例中,setState所处与异步环境中,所以同步执行,也就是不再进行等待直接修改state的值不进行请求合并,而state的值一旦被修改。react的视图就会更新。所以上面案例中,视图会被更新五次。
总结
表达不足,请多指教。
希望这些分享对大家有用。