美文网首页
React setState非同步更新问题的一丢丢见解

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

作者: 许小花花 | 来源:发表于2019-05-05 12:39 被阅读0次

    在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非同步更新问题的一丢丢见解

          本文链接:https://www.haomeiwen.com/subject/jjycoqtx.html