React setState非同步更新问题的一丢丢见解

在React中,通过setState来实现状态的修改更新,当this.setState()方法被调用后,会rerender实现视图的更新。整个流程如下图所示:


需要注意的是,setState对state的更新并非同步实现的,所以有时在调用this.state后直接获取修改的state值会发现依旧是更新前的值。

分析

首先明确三点:

  • 1.setState不会立刻改变React组件中state的值
  • 2.setState通过触发一次组件的更新来引发重绘
  • 3.多次setState函数调用产生的效果会合并

这是使用this.setstate需要get的三个基础点,一点一点进行分析

第一,为什么不会立刻改变?

首先明确,在React中,如果是由React引发的事件处理(比如通过onClick引发的合成事件处理)和组件生命周期函数内(比如componentDidMount),调用this.setState不会同步更新this.state,除此之外的setState调用会同步执行this.state。
所谓“除此之外”,指的是绕过React通过addEventListener直接添加的事件处理函数还有通过setTimeout/setInterval产生的异步调用
为什么由React引发的就不会同步?
在React的setState函数实现中,会根据一个变量isBatchingUpdates判断是直接更新this.state还是放到队列中回头再说,而isBatchingUpdates默认是false,也就表示setState会同步更新this.state,但是,有一个函数batchedUpdates,这个函数会把isBatchingUpdates修改为true,而当React在调用事件处理函数和自身生命周期之前就会调用这个batchedUpdates,也就是说,任何通过React引发的更新,都会触发这个batchedUpdates函数,导致isBatchingUpdatestrue,导致不会立即更新。而其他绕过了React的,则是可以立即更新的。

第二第三,为什么要合并触发?

性能更好啊,相当于节流,因为vdom算法和视图更新都是需要耗费性能的,所以应当尽量减少。

解决

那么如果我需要绕过这个batchedUpdates,或者说我就是需要立即执行,那么应该怎么办?
三点:

  • 1.使用回调函数
  • 2.使用setTimeout
  • 3.和渲染无关的状态尽量不要放在 state 中来管理
1、回调

setState 方法接收一个 function 作为回调函数。这个回掉函数会在 setState 完成以后直接调用,这样就可以获取最新的 state 。对于之前的例子,就可以这样:

this.setState({
  selection: value
}, this.fireOnSelect)
2、定时

定时器为什么可避免这个问题,上面已经说过了

3、和渲染无关的状态尽量不要放在 state 中来管理

通常 state 中只来管理和渲染有关的状态 ,从而保证 setState 改变的状态都是和渲染有关的状态。这样子就可以避免不必要的重复渲染。其他和渲染无关的状态,可以直接以属性的形式保存在组件中,在需要的时候调用和改变,不会造成渲染。

你可能感兴趣的:(React setState非同步更新问题的一丢丢见解)