模拟面试官setState-到底是同步还是异步

18次阅读

共计 1166 个字符,预计需要花费 3 分钟才能阅读完成。

官方对其描述是: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 管制的,所以表现出异步,当然了,想要知道更深层次的原因就需要去阅读一下相关的源码了,这里就不展开了,有兴趣的朋友可以读一读。

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

正文完
 0