关于setState,使用过react的人应该再熟悉不过了,在hooks还不那么普及的时候,除了使用函数式组件,我们使用最多的应该就是类创建react的组件了,而在类组件中我们通常会使用state来管理组件的数据变化及更新。

setState的使用注意事项

setState(updater, callback)这个方法是用来告诉react组件数据更新渲染。

在使用setState改变状态之后,立刻通过this.state去拿最新的状态往往可能并不容易拿到的。

要点1:

基于此如果需要拿到最新的state,根据官方给的方法就是在‘componentDidUpdate或者在setState的第二个参数的回调函数中获取

componentDidMount(){
this.setState({
date: 3,
}, function(){
console.log('callback',this.state.date) // date为 3
});
console.log('fn',this.state.date) // date为1
}

要点2:

对于同时累加多次的问题

componentDidMount(){
this.setState({
date: this.state.date + 1,
});
this.setState({
date: this.state.date + 1,
});
this.setState({
date: this.state.date + 1,
});
}
// 最后date的值只累加了一次,为2

我们的目标值可能是4,但是react最后给出的与我们目标值不一样,这是因为react为了考虑性能问题,防止重复渲染将setState方法统一在渲染前统一进行,之后再进行render

如果想要得到4,推荐再setState传function

componentDidMount(){
this.setState((state) => {
return {date: state.date + 1}
});
this.setState((state) => {
return {date: state.date + 1}
});
this.setState((state) => {
return {date: state.date + 1}
});
} // 最后得到目标值4

那么setState是同步的还是异步的?

从上面我们发现当我们在setState后没法立即拿到我们设置的值,可能很多人想说,因为setState是异步的。情况真的是这样吗,看下面的例子

// 定时器中
componentDidMount(){
setTimeout(() => {
this.setState({
date: 2
});
console.log('1111', this.state.date) // date为2
})
} // 或者监听函数
componentDidMount(){
document.getElementById('button').addEventListener('click', this.clicks)
} clicks = () => {
this.setState({
date:3,
})
console.log('addEventListener', this.state.date); // date为3
}

我们发现在在定时器或者是监听函数等原生方法中时,当我们设置setState,我们是可以同步的拿到最新的state的值得。

而根据react源码,和我个人的理解setState是其实用同步的操作来模仿的异步的行为。

我们知道react为了兼容各种浏览器,同时为了性能的考量有自己的合成事件,譬如onClick、onChang之类的。当我们在生命周期中或者合成事件中,setState将变成异步的行为,而在js原生事件中setState将变成同步的。

那react是如何区分的呢,其实可以简单的理解为,react对于异步的setState会给方法打上一个isBatchingUpdates,并将它放在一个处理state的队列中,当react其他任务执行完需要开始渲染前,将循环处理队列中的方法,同时更新state

而对于同步的setState则进行直接更新。

参考

https://github.com/facebook/react/issues/11527

https://github.com/olifer655/react/issues/12

React-setState的那些事儿的更多相关文章

  1. 动态修改JS对象的值及React setState

    一.在JS里使用(非ES6) 实现场景: 给一个空对象填充某一指定数组内的值 并随机生成数量 const fruit = ['apple', 'banana', 'orange'] let fruit ...

  2. 深入研究React setState的工作机制

    前言 上个月发表了一篇 React源码学习--ReactClass,但是后来我发现,大家对这种大量贴代码分析源码的形式并不感冒.讲道理,我自己看着也烦,还不如自己直接去翻源码来得痛快.吸取了上一次的教 ...

  3. react组件通信那些事儿

    父组件是调用组件的组件.现在看来,感觉父组件就是一个壳子,定义好壳子里面会有什么,而子组件是一个具体的实现,说明,会用到什么东西,如果有这些东西,会进行什么操作.总之,父组件是材料,有水和泥,子组件告 ...

  4. [Web 前端] 我不再使用React.setState的3个原因

    copy from : https://blog.csdn.net/smk108/article/details/85237838 从几个月前开始,我在新开发的React组件中不再使用setState ...

  5. 关于React setState的实现原理(二)

    React中的Transaction 大家学过sql server的都知道我们可以批量处理sql语句,原理其实都是基于上一篇我们说的Datch Update机制.当所有的操作均执行成功,才会执行修改操 ...

  6. 关于React setState的实现原理(三)

    前面提到事务即将结束时,会去调用FLUSH_BATCHED_UPDATES的flushBatchedUpdates方法执行批量更新,该方法会去遍历dirtyComponents,对每一项执行perfo ...

  7. 关于React setState的实现原理(一)

    前言 首先在学习react的时候就对setSate的实现有比较浓厚的兴趣,那么对于下边的代码,可以快速回答吗? class Root extends React.Component { constru ...

  8. react setState修改嵌套对象

    在react使用setState过程中,难免会遇到复杂的数据类型,,这里还要提醒一下setState 是异步操作行为,需要setState之后的结果做为参数,请求数据的话,可以配合 async  aw ...

  9. react setState里的作用域

    从接触racet开始,我们就认识了setState,它是对全局变量进去更新的一个重要方法, 不仅可以更新数据,还能在更新后执行方法时直接调用刚刚更新的数据 今天碰到的问题就在于它的作用域的先后问题 先 ...

  10. React setState和修改props触发的钩子

    1. setState的改变会触发4个生命周期钩子 shouldComponentUpdatecomponentWillUpdaterendercomponentDidUpdate 2. props的 ...

随机推荐

  1. 记一次“愉快”的lnmp环境的搭建

    愉快的lnmp环境搭建 后续更新 几个笔记记录 yum remove php-mysql yum -y install cmake autoconf wget gcc-c++ gcc zlib pcr ...

  2. mysql 随机选取一条符合条件的记录

    暂时记录下: SELECT *  FROM `kw_user` AS t1 JOIN ( SELECT ROUND( RAND( ) * ( ( SELECT MAX( id ) FROM `kw_u ...

  3. 通过修改EIP寄存器实现强行跳转并且注入DLL到目标进程里

    /* 描述 功能:通过修改EIP寄存器实现32位程序的DLL注入(如果是64位,记得自己对应修改汇编代码部分) 原理: 挂起目标进程,停止目标进程EIP的变换,在目标进程开启空间,然后把相关的指令机器 ...

  4. 一起来看看java并发中volatile关键字的神奇之处

    并发编程中的三个概念: 1.原子性 在Java中,对基本数据类型的变量的读取和赋值操作是原子性操作,即这些操作是不可被中断的,要么执行,要么不执行. 2.可见性 对于可见性,Java提供了volati ...

  5. 多种方法实现实现全排列 + sort调用标准函数库函数的简述

    全排列:所有不同顺序的元素组组成的一个集合.这里使用使用递归实现全排列. 使用递归算算法呢,首先我们先找一下结束的条件:我们要对一组元素(这里使用数字举例)实现全排列,临界条件就是递归到只有一个元素的 ...

  6. C#中的元组(Tuple)和结构体(struct)

    在正常的函数调用中,一个函数只能返回一个类型的值,但在某些特殊情况下,我们可能需要一个方法返回多个类型的值,除了通过ref,out或者泛型集合可以实现这种需求外,今天,讲一下元组和结构体在这一方面的应 ...

  7. 中文NER的那些事儿2. 多任务,对抗迁移学习详解&代码实现

    第一章我们简单了解了NER任务和基线模型Bert-Bilstm-CRF基线模型详解&代码实现,这一章按解决问题的方法来划分,我们聊聊多任务学习,和对抗迁移学习是如何优化实体识别中边界模糊,垂直 ...

  8. es6.4.0安装和配置IK+拼音插件 实现非全拼搜索

    安装IK分词器 一.进入到es的plugins文件夹创建文件夹analysis-ikmkdir analysis-ik二.下载ik压缩包文件wget https://github.com/medcl/ ...

  9. 使用find_if算法搜寻map的value

    // // main.cpp // map_find // // Created by PKU on 14-9-8. // Copyright (c) 2014年 PKU. All rights re ...

  10. 为什么说Zoho CRM是最好的销售预测系统?

    在文章的开头,我们来讲讲什么是销售预测--销售预测是指利用销售管道中的商机.已完成的配额.有望完成目标的销售团队或个人等关键信息对产品的销售数量与销售金额进行预测的手段.企业在制定销售计划时的重要任务 ...