React(7)异步的数据更改(setState 是异步行为)_qq20004604的博客-程序员ITS203

技术标签: 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

智能推荐

redis集群哈希一致性算法和哈希槽_我能在河边钓一整天的鱼的博客-程序员ITS203

先说普通哈希算法:让数据id的哈希值和redis集群的个数取模,得到的是几这个数据就存放在哪个redis服务器上普通哈希算法存在数据迁移的问题,即当集群数量增加或减少,原来数据的key与Redis序号对应的集群关系会改变,可能第一次数据1落在0号Redis上,第二次数据1就落在了2号机器上。这样就会出现”缓存穿透“一致性哈希算法一致性哈希算法首先弄了一个虚拟环,环上有n个节点,比如2的32次方个节点。这个环仅仅是逻辑上的一个算法。它先用redis机器序号+redis的ip生成唯一的一...

DataTable去除空行_diaohuyi6830的博客-程序员ITS203

protected void removeEmpty(DataTable dt) { List&lt;DataRow&gt; removelist = new List&lt;DataRow&gt;(); for (int i = 0; i &lt; dt.Rows.Count; i++) ...

百度五轮面试面经_怎么又有bug单的博客-程序员ITS203

第一轮shiro的组件分布式一致性算法zookeeper中哪些节点能参与投票netty零拷贝实现volatile,如何感知到变量变化的redis高可用http如何跨域?tcp如何长链接。http如何操作浏览器缓存。用过消息队列吗?怎么自己扩展validatorjwt组成 header payload 签名加密算法那些。rsa如何运用到jwt中synchronized和volatile的区别什么是上下文切换,URL解析过程http有那些方法,get那些进程和线程的区别。和

undefined reference to 问题总结(转载)_托拉丝丝的博客-程序员ITS203

转自:http://www.lingcc.com/2012/05/31/12093/“undefined reference to XXX”是一类挺常见的链接错误,原因通常是链接时找不到声明成extern类型的函数的定义点。不过这次遇到的undefined reference中的XXX函数明明在一个库中定义,而且该库明明已经在命令行用-l指定了,ld –verbose也显示能找到该库文件。

大中型企业的天网:Apache Geode_weixin_33743880的博客-程序员ITS203

2016年11月21日,Apache软件基金会(the Apache Software Foundation,ASF)宣布 Apache Geode已从Apache孵化器毕业成为顶级项目(Top-Level Project),表明该项目的社区和产品已根据ASF的精英流程和原则得到良好管理。 \初识Apache Geode\Apache Geode是一个相当成熟、强健的的数据管理平台,提供实时的、一...

分析:苹果iCloud战略意义大于iPhone 5_iteye_2060的博客-程序员ITS203

苹果计划发布最新版iPhone,但iCloud的发布更有战略意义。如果对苹果发布产品的重要性进行排名,其顺序应该是:iCloud、iOS 5,然后才是iPhone 5。苹果iCloud自WWDC大会上亮相后,似乎已经成为旧闻,该服务有可能腾飞。随着苹果发布iCloud,苹果由一家关注PC的厂商向关注多种设备厂商转型的时代即将到来。如果iCloud半途而废或出现其它问题,将是苹果辉煌史上的一个污点...

随便推点

根据子节点递归查找所有父节点ID_jannedarc_ruler的博客-程序员ITS203_递归找到父级id

递归获取所有父节点测试用例:参数说明:id为当前节点id;list为所有节点对像 @Override public List&lt;String&gt; queryParentIds(String id, List&lt;TaxCompany&gt; taxCompanyList) { //递归获取父级ids,不包含自己 List&lt;String&gt; parentIds = new ArrayList&lt;&gt;(); this.g

[转]MPI cluster技术简介与鸟哥的架设实例_安嘉的博客-程序员ITS203

MPI简介   MPI(Message Passing Interface)是消息传递并行程序设计的标准之一,当前通用的是MPI1.1规范。正在制定的MPI2.0规范除支持消息传递外,还支持MPI的I/O规范和进程管理规范。MPI正成为并行程序设计事实上的工业标准。  MPI的实现包括MPICH、LAM、IBM MPL等多个版本,最常用和稳定的是MPICH,曙光天潮系列的MPI以M

源码阅读_wangx_code的博客-程序员ITS203

我阅读源码的方法:1 官网或者一些博客中找到这里架构图,知道大概结构2 设计思路以及其中的设计模式3 源码debug+类图+时序图

php mysql 下拉菜单,通过PHP从MySql填充下拉菜单_美剧院线的博客-程序员ITS203

I wonder whether someone may be able to help me please.I have a MySql database containing several tables. My question revolves around the use of data from three of these, 'userdetails', 'detectors' an...

20年吐血整理:程序员全栈体系化学习路线与进阶地图_程序猿DD_的博客-程序员ITS203

左耳朵耗子的程序员练级攻略基本上发布完了,全程看下来,不得不说这些文章能看出来,是花了很大的心血,调动了耗子20年软件开发相关工作经验,结合他的亲身经历,分享他一路走来的...

任正非:华为是世界上最穷的高科技公司,比任何一个公司都穷_lin000001的博客-程序员ITS203

近日任正非接受了CNN采访,当被问及是否对华为未来的生存及盈利担心时,任正非表示我们对华为的生存是不会担心的。近日华为的第一季度的财报已经发布了,我们看到了华为恐怖的增长,总营销达到了1700多亿元,在接受采访的时候任正非也表示,他们已经感到今年的增长非常的猛,要控制合理的增长。在本次接受采访的时候,任正非表示华为要像苹果学习,要把产品的价格在做高一点,让所有的竞争对手都有生存空间,而不是...

推荐文章

热门文章

相关标签