React中的setState原理

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方法重新渲染页面

分析下面代码:

扫描二维码关注公众号,回复: 9765269 查看本文章
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。

附:分析过程

发布了19 篇原创文章 · 获赞 0 · 访问量 265

猜你喜欢

转载自blog.csdn.net/Joey_Tribiani/article/details/104468789