setState的问题?

  1. // react/packages/react-dom/src/__tests__/__snapshots__/ReactTestUtils-test.js.snap

setState是通过队列延迟执行操作实现的,通过isBatchingUpdates来判断setState是先存进state队列,还是直接更新,值为true则执行异步操作,false则直接同步更新

  1. class Test extends Component {
  2. state = {
  3. count: 0
  4. }
  5. componentDidMount(){
  6. this.setState({ count: this.state.count + 1 });
  7. console.log(this.state.count);
  8. setTimeout(() => {
  9. this.setState({ count: this.state.count + 1 });
  10. console.log("setTimeout: " + this.state.count);
  11. }, 0);
  12. }
  13. render(){
  14. }
  15. }

setState 并非真异步,只是看上去像异步。在源码中,通过 isBatchingUpdates 来判断 setState 是先存进 state 队列还是直接更新,如果值为 true 则执行异步操作,为 false 则直接更新。

那么什么情况下 isBatchingUpdates 会为 true 呢?在 React 可以控制的地方,就为 true,比如在 React 生命周期事件和合成事件中,都会走合并操作,延迟更新的策略。

但在 React 无法控制的地方,比如原生事件,具体就是在 addEventListener 、setTimeout、setInterval 等事件中,就只能同步更新。
一般认为,做异步设计是为了性能优化、减少渲染次数,React 团队还补充了两点。

  1. 保持内部一致性。如果将 state 改为同步更新,那尽管 state 的更新是同步的,但是 props不是。

  2. 启用并发更新,完成异步渲染。

image.png