美文网首页
Setstate到底是同步还是异步

Setstate到底是同步还是异步

作者: RoyChina | 来源:发表于2021-07-13 17:21 被阅读0次

    同步!

    在React中,如果是由React管理的事件处理(比如通过onClick引发的事件处理),调用setState不会同步更新this.state,除此之外的setState调用会同步执行this.state 。所谓“除此之外”,指的是绕过React通过addEventListener直接添加的事件处理函数,还有通过setTimeout/setInterval产生的异步调用。

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

    注意: setState的“异步”并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形式了所谓的“异步”,当然可以通过第二个参数 setState(partialState, callback) 中的callback拿到更新后的结果。

    isBatchingUpdates 和 batchedUpdates 主要是为了减少React管理的事件处理中 diff的次数为一次。

    setState()不是立刻更新组件。其可能是批处理或推迟更新。这使得在调用setState()后立刻读取this.state的一个潜在陷阱。
    就像这样:

    incrementCount() {
    this.setState({count: this.state.count + 1});
    }
    handleSomething() {
    this.incrementCount();
    this.incrementCount();
    this.incrementCount();
    }
    调用了3次incrementCount方法, 期望this.state.count的值是3, 但最后却是1
    本质上setState修改state的值是通过浅合并把新的值合并到state的对象上,如果多次修改,react会进行批次处理
    类似于:

    Object.assign(
    previousState,
    {count: state.count + 1},
    {count: state.count + 1},
    {count: state.count + 1},
    )
    之后的调用在同一周期中将会重写之前调用的值,因此数量仅会被加一。若之后的状态依赖于之前的状态,
    解决这个问题的方式:

    componentDidUpdate或一个setState回调(setState(updater, callback))
    当中的每个方法都会保证在更新被应用之后触发
    updater函数接收到的prevState 和 props保证都是最新的
    incrementCount() {
    this.setState((state) => {
    return {count: state.count + 1}
    });
    }
    handleSomething() {
    this.incrementCount();
    this.incrementCount();
    this.incrementCount();
    }
    setState什么时候会异步更新
    setState的执行流程:

    this.setState(newState)
    ==>
    newState存入pending队列
    ==>
    判断是否处于batch update
    ==>
    如果是的话就保存组件月dirtyComponents中,
    如果不是的话就遍历所有的dirtyComponents,调用updateComponent,更新pending state or props
    在 React 的 setState 函数实现中,会根据一个变量 isBatchingUpdates 判断是直接更新 this.state 还是放到队列中回头再说,
    而 isBatchingUpdates 默认是 false,也就表示 setState 会同步更新 this.state,
    但是,有一个函数 batchedUpdates,这个函数会把 isBatchingUpdates 修改为 true,
    而当 React 在调用事件处理函数之前就会调用这个 batchedUpdates,造成的后果,就是由 React 控制的事件处理过程 setState 不会同步更新 this.state。

    setState会导致re-rederning, 而re-rederning的代价是昂贵的, 所以他们会尽可能的把多次操作合并成一次提交。
    因为当传入的是一个函数时,state读取的是pending队列中state的值
    setState什么时候会异步更新, 什么时候会同步更新
    React是根据isBatchingUpdates来合并更新的, 那么当调用setState的方法或者函数不是由React控制的话, setState自然就是同步更新了。

    如componentDidMount等生命周期以及React的事件即为异步更新,这里不显示具体代码。
    如自定义的浏览器事件,setTimeout,setInterval等脱离React控制的方法, 即为同步更新

    相关文章

      网友评论

          本文标题:Setstate到底是同步还是异步

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