React中setState

@wanqiuz 2018-04-27 06:44:30发表于 wanqiuz/blog-articles ReactsetState

1 setState更新状态是同步还是异步

在React中有三种事件处理,分别为
(1) 由React引发的事件处理(比如通过onClick引发的事件处理)。-----异步更新state
(2) 绕过React通过addEventListener直接添加的事件处理函数。-----同步更新state
(3) 通过setTimeout/setInterval产生的异步调用。-----同步更新state

三种事件处理的代码如下:

class Test1 extends React.Component {

  onClick() {
    this.setState({count: this.state.count + 1});
  }
  
  onClickLater() {
    setTimeout(() => {
      this.onClick();
    });
  }
  
  render() {
    return (
      <div>
        <div>{this.state.count}
          <button onClick={this.onClick.bind(this)}>Increment</button>
          <button id="btn-raw">Increment Raw</button>
          <button onClick={this.onClickLater.bind(this)}>Increment Later</button>
        </div>
      </div>
    );
  }
 componentDidMount() {
    document.querySelector('#btn-raw').addEventListener('click', this.onClick);
  }
}

原因:在React的setState函数实现中,会根据一个变量isBatchingUpdates判断是直接更新this.state还是放到队列中回头再说,而isBatchingUpdates默认是false,也就表示setState会同步更新this.state,但是,有一个函数batchedUpdates,这个函数会把isBatchingUpdates修改为true,而当React在调用事件处理函数之前就会调用这个batchedUpdates,造成的后果,就是由React控制的事件处理过程setState不会同步更新this.state。

2 setState异步更新到底发生了什么

当调用 setState 时,React将传递给 setState 的对象合并到组件的当前状态。然后调用shouldComponentUpdate生命周期方法。如果该方法返回true,则会构建一个新的 React 元素树,React 会将这个新树与上一个元素树用DIFF算法比较,然后高效的更新元素树。

3 setState第二个可选参数是什么以及它的作用?

它是一个回调函数,在setState调用之后,以及component re-render后才执行.
之所以不常提到它,是因为setState是异步的,所以需要回调函数。最后是用另一个生命周期这个回调函数想做的事情,当然,知道它存在也是有好处的。

this.setState(
  { username: 'tylermcginnis33' },
  () => console.log('setState has finished and the component has re-rendered.')
)

4 下列代码有什么错误?

this.setState((prevState, props) => {
  return {
    streak: prevState.streak + props.count
  }
})

没错。它不太常用,但是你可以传递一个函数给setState(函数是一等公民),这个函数接收前一个时刻的state和props,并且返回一个新state。虽然这个用法不太常见,但是如果你想基于先前的state设置新的state,强烈建议这么做。

参考并感谢: