官方对其描述是:State Updates May Be Asynchronous.

也就是说,setState 表现出来可能是同步的也可能是异步的,要根据情况的不同来进行判断。

实战例子

下面是一个 setState 的例子,猜猜答案是什么?

class App extends React.Component {  state = { val: 0 }  componentDidMount() {    this.setState({ val: this.state.val + 1 })    console.log(this.state.val)    this.setState({ val: this.state.val + 1 })    console.log(this.state.val)    setTimeout(_ => {      this.setState({ val: this.state.val + 1 })      console.log(this.state.val);      this.setState({ val: this.state.val + 1 })      console.log(this.state.val)    }, 0)  }  handleClick = () => {    this.setState({ val: this.state.val + 1 })    console.log(this.state.val)    this.setState({ val: this.state.val + 1 })    console.log(this.state.val)  };  render() {    return <div onClick={handleClick}{this.state.val}</div>  }}

答案是 0 0 2 3,当我们点击 div 标签时,输出为 3 3

在 React 中,当在生命周期或者是 React 的合成事件里调用 setState 就会表现出异步,而如果你是在原生事件中或者是通过 setTimeout/setInterval 产生的异步调用里进行 setState 则会表现出同步。

为什么?

我们通过上面的例子知道了在什么情况下,它会表现出不同的结果,但是为什么会这样呢?

这里先明确一点,setState 表现出的异步不是指在 React 内部是通过异步实现的,其原本的执行过程都是同步的,只是在 React 中,为了优化所作的批处理机制给开发者造成了一种异步的假象。

那为啥原生事件和 setTimeout/setInterval 里会表现出同步呢?是因为这两者都脱离了 React 的执行环境,所以 React 的批处理机制并没有对其进行处理,所以表现出来就是同步的。而当我们使用如 onClick 的时候,我们使用的是 React 提供的合成事件,也就是说这是受 React 管制的,所以表现出异步,当然了,想要知道更深层次的原因就需要去阅读一下相关的源码了,这里就不展开了,有兴趣的朋友可以读一读。

非常感谢您的阅读,欢迎关注、转发、分享支持我。