• setState到底是异步还是同步?


    在介绍这个问题之前,我们先来看一下一个例子:

    state = {
        number:1
    };
    componentDidMount(){
        this.setState({number:3})
        console.log(this.state.number)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述
    看完这个例子,也许很多小伙伴会下意识的以为setState是一个异步方法,但是其实setState并没有异步的说法,之所以会有一种异步方法的表现形式,归根结底还是因为react框架本身的性能机制所导致的。因为每次调用setState都会触发更新,异步操作是为了提高性能,将多个状态合并一起更新,减少re-render调用。
    试想一下如果在组件中有以下这样一段代码执行

    for ( let i = 0; i < 100; i++ ) {
        this.setState( { num: this.state.num + 1 } );
    }
    
    • 1
    • 2
    • 3

    如果setState是一个同步执行的机制,那么这个组件会被重新渲染100次,这对性能是一个相当大的消耗。
    显然,React也是想到了这个问题,因此对setState做了一些特殊的优化:

    React会将多个setState的调用合并为一个来执行,也就是说,当执行setState的时候,state中的数据并不会马上更新。
    
    • 1

    这也很好的印证了刚才提到的那个例子。
    但是往往在实际的开发工作中,我们可能需要同步的获取到更新之后的数据,那么怎么获取呢?下面介绍几种常用的方法:
    回调函数
    setState提供了一个回调函数供开发者使用,在回调函数中,我们可以实时的获取到更新之后的数据。还是以刚才的例子做示范:

    state = {
        number:1
    };
    componentDidMount(){
        this.setState({number:3},()=>{
            console.log(this.state.number)
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述
    这个时候大家可以看到控制台打印的数据就是最新的了,我们也就实时的获取到了最新的数据。
    setTimeout
    上面我们讲到了,setState本身并不是一个异步方法,其之所以会表现出一种异步的形式,是因为react框架本身的一个性能优化机制。那么基于这一点,如果我们能够越过react的机制,是不是就可以令setState以同步的形式体现了呢?
    说再多文字不如代码实践,实践才是检验真理的唯一标准,下面我们还是以之前的例子为基础改造一下代码:

    state = {
        number:1
    };
    componentDidMount(){
        setTimeout(()=>{
          this.setState({number:3})
          console.log(this.state.number)
        },0)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    可以看见此时控制台打印的数据是最新的数据。这也完美的印证了我们的猜想是正确的。
    原生事件中修改状态
    上面已经印证了避过react的机制,可以同步获取到更新之后的数据,那么除了setTimeout以外,还有在原生事件中也是可以的。还是看一下例子:

    state = {
        number:1
    };
    componentDidMount() {
        document.body.addEventListener('click', this.changeVal, false);
    }
    changeVal = () => {
        this.setState({
          number: 3
        })
        console.log(this.state.number)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述
    经过实践,同样这种方法也是可行的。
    setState本身并不是异步,只是因为react的性能优化机制体现为异步。在react的生命周期函数或者作用域下为异步,在原生的环境下为同步。

  • 相关阅读:
    mariadb
    一、创建线程的三种方式
    Hadoop笔记-01概述
    Revit导入Cad图元丢失不正确解决和链接CAD功能
    WebRTC系列 -- iOS 音频采集之 ADM、APM和AudioState
    某电商网站的数据库设计(6)——创建查询销售数据的视图
    NB15 牛群编号的回文顺序II
    云计算与大数据第四章 云计算系统监题库及答案
    刷题记录:牛客NC16708[NOIP2002]过河卒
    可编程逻辑器件软件测试
  • 原文地址:https://blog.csdn.net/weixin_47450807/article/details/124913534