背景:
前提摘要:很多面试官都会问React中的 setState
到底异步还是同步?
那么他到底是同步还是异步呢?
setState的不同现象大致分为两种情况
- React 事件系统中的 合成事件 (例如:
onClick
, onChange
)和 React的生命周期中,它是’’异步’’的,注意我说的是带引号的异步。
- 在原生事件,或者
setTimeout
中(基于 event loop
模型) ,可以理解为setState是同步的,因为你能拿到最新的state。
我们先来说说第一种情况
通过代码来印证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
import React from "react";
class Home extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; }
componentDidMount() { this.setState({count: this.state.count + 1}); console.log("步骤1>>>>" + this.state.count);
this.setState({ count: this.state.count + 1 }, () => { console.log("步骤3>>>>" + this.state.count); });
this.setState( (prevState) => { console.log("步骤2>>>>" + prevState.count); return { count: prevState.count + 1 }; }, () => { console.log("步骤4>>>>" + this.state.count); } ); }
render() { return <div></div>; } }
export default Home;
|
在console上的执行顺序是
步骤1>>>>0
步骤2>>>>1
步骤3>>>>2
步骤4>>>>2
注意我写的步骤顺序
如果跟你想的有差异,来解释一波(以下思路纯个人理解)
首先,React在每次渲染之前会维护一个state队列,将每次setState的值进行合并,最后进行一次渲染。
我们把代码拿过来:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
componentDidMount() { this.setState({count: this.state.count + 1}); console.log("步骤1>>>>" + this.state.count);
this.setState({ count: this.state.count + 1 }, () => { console.log("步骤3>>>>" + this.state.count); });
this.setState( (prevState) => { console.log("步骤2>>>>" + prevState.count); return { count: prevState.count + 1 }; }, () => { console.log("步骤4>>>>" + this.state.count); } ); }
|
有没有清晰一点,如果没有那等会再看,先来看看第二种情况
第二种情况
也就是setTimeout和原生事件,这里就不展示原生事件了。
先来看一波简单直接的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
componentDidMount() {
this.setState({ count: this.state.count + 1 }); console.log("生命周期中", this.state.count); setTimeout(() => { console.log("setTimeout1", this.state.count); this.setState({ count: this.state.count + 1 }); this.setState({ count: this.state.count + 1 }); this.setState({ count: this.state.count + 1 }); this.setState({ count: this.state.count + 1 }); this.setState({ count: this.state.count + 1 }); console.log("setTimeout2:", this.state.count); }, 0); }
|
本文代码 :codesandbox
如果你还想知道React内部实现原理,可以精读这篇文章 你真的理解setState吗?
我个人感觉讲解非常清晰了。
感谢阅读。