setState原理
React中的页面更新核心思想围绕着state来进行,那么更新state也就是setState的原理是什么样呢?
分析以下代码:
import React from "react";
export default class extends React.Component{
state={
count:1
}
add = ()=>{
this.setState({count:this.state.count+1})
console.log("add");
this.setState({count:this.state.count+1})
console.log("add");
this.setState({count:this.state.count+1})
console.log("add");
}
render (){
console.log("render");
return(
<div>
<h2>{this.state.count}</h2><button onClick={this.add}>+</button>
</div>
)
}
}
根据运行结果可以发现,点击“+”按钮,add会输出三次,也表示三个setState语句都会被执行,然而我们得到的结果显示我们的count值只增加了一次,变为2,而并非增加三次变为4,这是为什么呢?
演示结果分析:
React整个系统中有一个叫做事务的概念,该事务有个状态值isTrans,默认值为false,意味着当前事务没有开启,或者说当前没有事务这个概念,上面代码中,button按钮绑定了一个叫做add的点击事件(委托在了document身上),当按钮被点击时,isTrans这个状态值会被设置为true,意味着开启了一个事物,开始触发事件,事件里面有this.setState函数的调用,而setState内部维护了一个数组(可以理解为一个等待更新的队列queue,注意还没有更新,只是等待更新),然后把对象{count:2}放入队列,然后进入下一个流程判断isTrans是真还是假,如果isTrans为true意味着事物还没结束,则结束setState方法,然后执行下一语句输出"add"。所以不会更新state,第二次调用同样如此,到了最后一次调用state的时候,事物还是没有结束,但是add方法已经调用结束,因此isTrans的值会被设置为false,意味着事务已经结束,进入更新流程,把对象{count:2}放入队列后,读取queue队列中的对象(待更新的值),并且合并(按照顺序取出来合并),继续下一步判断isTrans的真假情况,判断为假,然后更新state,清空queue(等待下次事物过来),调用render方法重新渲染页面。
总结步骤:1、读取queue队列并且合并
2、修改state的值
3、clear queue清空队列
4、调用render方法重新渲染页面
分析下面代码:
import React from "react";
export default class extends React.Component {
state = {
count: 1
}
add = () => {
Promise.resolve().then(
() => {
this.setState({ count: this.state.count + 1 })
console.log("add");
this.setState({ count: this.state.count + 1 })
console.log("add");
this.setState({ count: this.state.count + 1 })
console.log("add");
}
)
console.log("end");
}
render() {
console.log("render");
return (
<div>
<h2>{this.state.count}</h2><button onClick={this.add}>+</button>
</div>
)
}
}
演示结果分析
这段代码和上段代码的区别就是这段代码中的setState是在异步的环境中的,它的结果是state会被设定为4。
因为是在异步的环境中运行,那么add方法调用时,异步的代码会被扔到异步任务队列里,执行完console.log(“end”)语句后意味着该方法调用结束,然后执行异步的代码,此时由于事物的isTrans因为方法的调用结束而被设置为false,也表示这事务的结束,因此每次执行setState函数的时候进入到queue的时候把对象{count:2}放进去,然后直接修改state,清空queue,调用render,以此类推,执行三次之后state中的count值已经被修改为了4。
附:分析过程