React(7)异步的数据更改(setState 是异步行为)_react js 根据 异步 结果 修改-程序员宅基地

技术标签: React 教程  React教程  React  

与Vue不同,React的设置变量是异步的。

13、setState 是异步行为

setState()

这是一个异步操作,如:

class HelloWord extends React.Component {
    
    constructor(props) {
        super(props);
        this.state = {
            count: 0
        }
        this.clickCountAsync = this.clickCountAsync.bind(this)
    }

    // 渲染函数,this 指向实例本身
    render() {
        return <div>
            <button onClick={
   this.clickCountAsync}>异步增加count</button>
        </div>
    }

    clickCountAsync() {
        console.log('【异步】setState之前,count的值:', this.state.count)
        this.setState({
            count: this.state.count + 1
        })
        console.log('【异步】setState之后,count的值:', this.state.count)
    }
}

会发现,两个 log 语句,输出的结果的值,都是一样的。

原因是 React 会合并多个 setState,然后统一更新;

那么如何获取更新后的数据,答案是通过回调函数;

说明见注释

class HelloWord extends React.Component {
    
    constructor(props) {
        super(props);
        this.state = {
            count: 0,
            anotherCount: 0
        }
        this.clickCountAsync = this.clickCountAsync.bind(this)
        this.clickCountSync = this.clickCountSync.bind(this)
    }

    // 渲染函数,this 指向实例本身
    render() {
        return <div>
            <button onClick={
   this.clickCountAsync}>异步增加count</button>
            <br/>
            <button onClick={
   this.clickCountSync}>增加count,并同步更新计数器二的值等于异步增加后的count</button>
            <br/>
            计数器二:{
   this.state.anotherCount}
        </div>
    }

    clickCountAsync() {
        console.log('【异步】setState之前,count的值:', this.state.count)
        this.setState({
            count: this.state.count + 1
        })
        console.log('【异步】setState之后,count的值:', this.state.count)
    }

    clickCountSync() {
        // 通过setState 更新 state.count 的值
        this.clickCountAsync()
        // 1、这里是更新前的值
        console.log('【同步】setState之前,count的值:', this.state.count)
        this.setState((prevState, props) => {
            // 3、这里的回调函数,是更新后执行(即
            console.log(prevState, props)
            // 返回值就像设置 setState 的参数一样
            return {
                anotherCount: prevState.count
            }
        })
        // 2、这里也是更新前的值
        console.log('【同步】setState之后,count的值:', this.state.count)
    }
}

当然,这又出现一个问题,那就是假如我调用一个方法,分别修改了 A 变量,然后又调用某个方法需要修改 B 变量,并且 B 变量依赖于 A 变量修改后的值(这就是以上场景);

可是假如我又需要调用第三个方法修改 C 变量,并且 C 的值依赖于 B 修改后的值。那么这就有问题了。

原因是:

  1. React 里并不存在类似 Vue 的 computed/watch 这样的计算属性。如果需要实现,那么可能需要引入额外的库(watch.js/Rx.js/mobx);
  2. setState 本身是异步的,并且回调函数获取变更后的值,也是异步的。因此在场景复杂的情况下,你很难判断哪一个 setState 的回调函数,会优先执行;

解决办法:

  1. 一个是引入额外的库,仿 Vue.js;
  2. 考虑使用生命周期函数 componentWillUpdate(nextProps, nextState),将依赖的变量的修改逻辑,添加到这个函数里,如下面代码,可以解决部分场景的问题;
componentWillUpdate(nextProps, nextState) {
    nextState.anotherCount *= 2
    console.log(nextProps, nextState)
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq20004604/article/details/79318197

智能推荐

十进制转二进制(C++)_c++十进制转二进制-程序员宅基地

文章浏览阅读4.8w次,点赞34次,收藏116次。除二取余法相信大家应该都知道,十进制转k进制的方法常用的就是除k取余的方法,这里针对这个方法,给出了C++的代码。需要注意的是,除二取余的方法,对于余数的选取是从后往前取的,所以在代码中,也要解决这个问题才行。思路分析模仿不停地除2的过程,每次除2之后用 % 取余数i;用 / 作为下一次除2的被除数temp;j初始化为1,每次除了2之后,j= j*10。最终输出的结果result在..._c++十进制转二进制

Python+Selenium自动化-清空输入框、输入内容、点击按钮-程序员宅基地

文章浏览阅读1.1w次,点赞3次,收藏33次。Python+Selenium自动化-清空输入框、输入内容、点击按钮1.输入内容send_keys('valve'):输入内容valve#定位输入框input_box = browser.find_element_by_id('kw')try: #输入内容:selenium input_box.send_keys('sel..._python selenium input 点击

DockerFlie中设置crontab定时任务,以及new crontab file is missing newline before EOF, can‘t install.错误的解决方法-程序员宅基地

文章浏览阅读6.3k次,点赞2次,收藏8次。DockerFlie中设置crontab定时任务new crontab file is missing newline before EOF, can't install.错误的解决方法问题描述:(系统ubuntu)想要在docker容器创建是就自动新建一个crontab定时任务,用于项目打包成docker容器时可以定时在容器中执行一些命令解决方法:首先,在项目目录下创建cro..._new crontab file is missing newline before eof, can't install.

网络驱动发送队列的停止和冻结_netif_stop_subqueue-程序员宅基地

文章浏览阅读2.8k次,点赞4次,收藏20次。内核中的枚举类型netdev_queue_state_t定义了三种情况,包括设备驱动层面的发送队列停止,协议栈层面的发送队列停止以及发送队列的冻结。另外,定义了三个宏表示了三种组合,其中QUEUE_STATE_ANY_XOFF包含驱动和协议栈两个层面的发送队列停止;其它两个定义如下所示,意义直观。enum netdev_queue_state_t { __QUEUE_STATE_DRV_..._netif_stop_subqueue

使用批处理命令bat文件快速一键启动mysql_maria db 启动bat文件 csdn-程序员宅基地

文章浏览阅读1.3w次。第一步,新建一个文本文档; 第二步,在文本文档中输入如下命令:cmd /k "cd C:\Program Files (x86)\MySQL\MySQL Server 5.1\bin && mysql -hlocalhost -uroot -p"net start mysql第三步,跟文本文档命名,随便命名成自己认为有意义的名字即可,重点是文件的后缀名必须改为.bat,到此,任务完成。可以体验一_maria db 启动bat文件 csdn

vbs画动态爱心代码_前端必看之如何用CSS3画一个八卦和爱心-程序员宅基地

文章浏览阅读719次。昨天雷雨交加,燥热有所缓解。今晨空气清新,再加上马上三天小长假,心情很不错,祝各位小长假玩的开心。那么,今天就用CSS3做些“不正紧”的事:画八卦和爱心。CSS3我们一般都是用来进行布局,在工作中很少会刻意去用它画画,毕竟这有点耗时间。一、八卦css3绘制八卦分析:它就是多个圆叠加的效果。1、给body加个背景色,否则看不清八卦的白色部分:body{background:#efefef;}2、画一..._vbs 画

随便推点

python+scrapy+selenium爬虫_info: scrapy 2.8.0 started (bot: sci_baike_seleniu-程序员宅基地

文章浏览阅读2.3w次,点赞2次,收藏26次。python配置_info: scrapy 2.8.0 started (bot: sci_baike_selenium)

微信小程序 点击按钮 底部弹出菜单_小程序点击按钮出现菜单栏-程序员宅基地

文章浏览阅读6.1k次,点赞2次,收藏6次。页面:js:效果:_小程序点击按钮出现菜单栏

大数据环境-程序员宅基地

文章浏览阅读123次。大数据环境

PyQt5学习笔记(2) 初识PyQt,Hello Pyqt_labhello.setgeometry(70, 60, size.width(), size.he-程序员宅基地

文章浏览阅读168次。# -*- coding: utf-8 -*-# @Time : 2019/11/24 16:18# @Author : dailinqing# @Email : [email protected]# @File : hello_pyqt.py# @Software: PyCharmdimport sysfrom PyQt5 import QtCore,Qt..._labhello.setgeometry(70, 60, size.width(), size.height())

【ENSP模拟器】链路技术(HCNA)——LACP及链路聚合配置实例_基于ensp的lacp聚合仿真设计与实现csdn-程序员宅基地

文章浏览阅读4.1k次,点赞2次,收藏23次。LACPLACP即链路聚合控制协议,它是Link Aggregattion Control Protocol的简称。该协议定义在IEEE 802.3AD中(IEEE 802.3AD包含了LACP和Marker Protocol这两个协议)。在设备上实现链路聚合时,通常可以有两种模式:一种称为手工负载分担模式;另一种称为LACP模式。显然,LACP模式实现起来会增加设备本身的复杂度,但是它的自动化程度更高,并且可以避免一些人为的错误。例如,如图所示中,如果采用手工模式在S1和S2上配置聚合端口,就有可_基于ensp的lacp聚合仿真设计与实现csdn

CSAPP深入理解计算机系统实验datalab解析_/* * float_i2f - return bit-level equivalent of ex-程序员宅基地

文章浏览阅读2.3w次,点赞10次,收藏49次。看完这一本《CSAPP深入理解计算机系统》_/* * float_i2f - return bit-level equivalent of expression (float) x * resul

推荐文章

热门文章

相关标签