setState

2018-01-25  本文已影响56人  strong9527

参考文章:

Lucas HC知乎答案

程墨Morgan知乎专栏

深入React书

react官方解释:setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState()a potential pitfall.

setState的调用到底发生了什么,在调用setState时,react的表现得真的全都是异步的吗?

setState方法调用

在调用此方法后,react会将改变的状态放进一个队列中(pending队列),之后调用enqueueUpdate方法判断是否处于批量处理更新模式,如果判断是正确的那么就将组件保存到dirtyComponents中。enqueueUpdate方法判断不是批量更新模式,那么直接就更新state状态。

[站外图片上传中...(image-7a43f6-1516868303926)]

可以看到这其中有一个关键就是enqueueUpdate函数的判断,如果判断不是批量更新模式那么setState就是立即更新state的值。


this.setState({val: this.state.val + 1})
console.log(this.state.val) // 第一次输出

this.setState({val: this.state.val + 1})
console.log(this.state.val) // 第二次输出

setTimeout(() => {
    this.setState({val: this.state.val + 1})
    console.log(this.state.val) // 第三次输出
    
    this.setState({val: this.state.val + 1})
    console.log(this.state.val) // 第四次输出
})

这四个输出的console分别是 0、0、2、3

可以看到前两次setState并没有直接改变state的值,而timeOut里面的setState就同步的改变了state的值。所以,直接说setState是异步更新是不严谨的。

由 React 控制的事件处理过程 setState 不会同步更新 this.state!

在 React 控制之外的情况, setState 会同步更新 this.state!

也就是说在react内部自定义事件绑定的事件函数,是异步更新,而用addEventListener或setTimeout非react内部绑定事件函数就是同步更新。

函数式setState

顾名思义,也就是setState的参数不再是一个对象,而是一个函数,这样就可以保障setState安全进行批次处理,setState的值就不会出现覆盖现象。

function incre() {
    return {score: this.state.score + 1}
}

function handleState() {
    this.setState( incre )
    this.setState( incre )
    this.setState( incre )
}

函数式setState能够保证,每一次调用incre函数时,之前队列中的state修改结果都已经完成。

而函数式setState也并不是完美的,

function incrementMultiple() {
  this.setState(increment);
  this.setState(increment);
  this.setState({count: this.state.count + 1});
  this.setState(increment);
}

最后的结果count只增加了2,而不是4,因为遇到了传统的setState方式,所以会把之前的函数时setState的修改效果清空。

上一篇 下一篇

猜你喜欢

热点阅读