1.setState更新状态的2种写法

(1). setState(stateChange, [callback])------对象式的setState

​ 1.stateChange为状态改变对象(该对象可以体现出状态的更改)

​ 2.callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用

代码展示:

import React, { Component } from 'react'export default class Demo extends Component {state = {count:0}add = ()=>{//对象式的setState//更新状态this.setState({count:this.state.count+1},()=>{console.log(this.state.count);//3})this.setState({count:this.state.count+2},()=>{console.log(this.state.count);//3})this.setState({count:this.state.count+3},()=>{console.log(this.state.count);//3})console.log('12行的输出',this.state.count); //0 }render() {return (<div><h1>当前求和为:{this.state.count}</h1><button onClick={this.add}>点我+1</button></div>)}
}

相信小伙伴们发现了打印的结果的不同,如果在第二个参数里打印就能拿到最新的结果,如果在对象形式的setState外面打印,却只能拿到初始值,这里表示这种情况下setState是异步的,

原因就是:

在 React 的 setState 函数实现中,会根据一个变量 isBatchingUpdates 判断是直接更新 this.state 还是放到一个updateQueue中延时更新,而 isBatchingUpdates 默认是 false,表示 setState 会同步更新 this.state;但是,有一个函数 batchedUpdates,该函数会把 isBatchingUpdates 修改为 true,而当 React 在调用事件处理函数之前就会先调用这个 batchedUpdates将isBatchingUpdates修改为true,这样由 React 控制的事件处理过程 setState 不会同步更新 this.state,而是异步的。

同样小伙伴们也发现了,明明调了三次的对象形式的setState却只取了最后一次修改的值,这是因为react内部为了优化setState()的批处理,会对setState()进行合并,并且对对相同属性的设置只保留最后一次的设置

总结:
所以说setState本身是同步的,一旦走了react内部的合并逻辑,放入了updateQueue队列中就变成异步了,而代码中的函数是react控制的,内部会走合并逻辑,所以这里的setState 不但是合并的也是异步的

相信小伙伴们就会问了,那怎么才能在异步执行的情况下,让每一次的setState调用都起效果呢,别急第二种写法就可以解决这种问题

(2). setState(updater, [callback])------函数式的setState

​ 1.updater为返回stateChange对象的函数。

​ 2.updater可以接收到state和props。

​ 4.callback是可选的回调函数, 它在状态更新、界面也更新后(render调用后)才被调用。

代码展示:

import React, { Component } from 'react'export default class Demo extends Component {state = {count:0}add = ()=>{//对象式的setState//更新状态//函数式的setStatethis.setState( state => ({count:state.count+1}))this.setState( state => ({count:state.count+2}))this.setState( state => ({count:state.count+3}))console.log('12行的输出',this.state.count); //0 }render() {return (<div><h1>当前求和为:{this.state.count}</h1><button onClick={this.add}>点我+1</button></div>)}
}

通过执行发现当前求和值变成了6,但是最终打印结果还是0,说明这种写法还是异步的。

2.利用setTimeout绕过react内部的合并逻辑

代码展示:

import React, { Component } from 'react'export default class Demo extends Component {state = {count:0}add = ()=>{//对象式的setState//更新状态setTimeout(() => {this.setState({count:this.state.count+1},()=>{console.log(this.state.count);//1})this.setState({count:this.state.count+2},()=>{console.log(this.state.count);//3})this.setState({count:this.state.count+3},()=>{console.log(this.state.count);//6})console.log('12行的输出',this.state.count); //6}, 100);}render() {return (<div><h1>当前求和为:{this.state.count}</h1><button onClick={this.add}>点我+1</button></div>)}
}

通过运行发现,成功绕开了合并逻辑,打印出了6。

3.总结:

异步的情况:
由React控制的事件处理函数,以及生命周期函数调用setState时表现为异步 。大部分开发中用到的都是React封装的事件,比如onChange、onClick、onTouchMove等(合成事件中),这些事件处理函数中的setState都是异步处理的。

同步的情况:
React控制之外的事件中调用setState是同步更新的。比如原生js绑定的事件,setTimeout/setInterval,ajax,promise.then内等 React 无法掌控的 APIs情况下,setState是同步更新state的

对象形式

1.函数式的setState的简写方式(语法糖)

2.批处理,对相同变量进行的多次处理会合并为一个,并以最后一次的处理结果为准

函数形式:

链式调用,React 会把我们更新 state 的函数加入到一个队列里面,然后,按照函数的顺序依次调用。同时,为每个函数传入 state 的前一个状态

使用原则:

(1).如果新状态不依赖于原状态 ===> 使用对象方式

(2).如果新状态依赖于原状态 ===> 使用函数方式

(3).如果需要在setState()执行后获取最新的状态数据, 要在第二个callback函数中读取

react中的setState详解相关推荐

  1. js路由在php上面使用,React中路由使用详解

    这次给大家带来React中路由使用详解,React中路由使用的注意事项有哪些,下面就是实战案例,一起来看一下. 路由 通过 URL 映射到对应的功能实现,React 的路由使用要先引入 react-r ...

  2. React中使用Vditor详解(自定义图片)

    安装 npm install vditor -s 引用 导入依赖包 import Vditor from "vditor"; 导入样式 import "vditor/sr ...

  3. React中的Hooks详解

    1.概述 React官方网站原文:Hooks 是一项新功能提案,可让您在不编写类的情况下使用 state(状态) 和其他 React 功能. 我总结了下使用Hooks的理由: 1.解决class中的代 ...

  4. react中的state详解

    state 理解:state是组件对象最重要的属性,值是对象(可以包含多个key-value组合) state中的值可以修改,修改的唯一方法是调用this.setState,每次修改以后,自动调用 t ...

  5. webpack搭建php服务器,webpack搭建react开发环境步骤详解

    这次给大家带来webpack搭建react开发环境步骤详解,webpack搭建react开发环境的注意事项有哪些,下面就是实战案例,一起来看一下.mkdir react-redux && ...

  6. ALSA声卡驱动中的DAPM详解之四:在驱动程序中初始化并注册widget和route

    前几篇文章我们从dapm的数据结构入手,了解了代表音频控件的widget,代表连接路径的route以及用于连接两个widget的path.之前都是一些概念的讲解以及对数据结构中各个字段的说明,从本章开 ...

  7. Asp.net中GridView使用详解(引)【转】

    Asp.net中GridView使用详解(引) GridView无代码分页排序 GridView选中,编辑,取消,删除 GridView正反双向排序 GridView和下拉菜单DropDownList ...

  8. Linux中iptraf命令详解(IP局域网监控工具)

    2019独角兽企业重金招聘Python工程师标准>>> Linux中iptraf命令详解(IP局域网监控工具) 发布时间:2017-12-27 20:46:03   作者:佚名    ...

  9. ArcGIS Engine中的Symbols详解

    转自原文 ArcGIS Engine中的Symbols详解 本文由本人翻译ESRI官方帮助文档.尊重劳动成果,转载请注明来源. Symbols ArcObjects用了三种类型的Symbol(符号样式 ...

最新文章

  1. “元宇宙”数字化理解
  2. 计算机二级find,Excel函数-find、if和iferror-计算机二级Office
  3. dao层通用封装_DAO层–救援通用
  4. 中国联通董事李福申辞任
  5. mysql my.ini配置优化_求高手帮我优化一下 mysql 的 my.ini
  6. theadClasses设置Bootstrap Table表头样式
  7. html搜索联系人,联系人列表.html
  8. java 不支持,不支持Java Sound格式
  9. CEF3 C++接口实现自定义浏览器[simple version]
  10. 订单拆单-产品逻辑分析研究
  11. 武汉青少年计算机编程,武汉青少年编程学习
  12. AMADA阿玛达工控机维修折弯机主机维修R027-00主板故障处理
  13. SAS系统学习之初探
  14. 用Python做雷霆战机小游戏【附素材+源码】
  15. 穆帅战巴萨督编励志片 内含梅西踢皇马球迷皮克5指山
  16. yy账号找回方法详解
  17. 程序员的悲哀--动车追尾
  18. 上线两个月,微信小程序给那些用身体支持它的人带来了什么?
  19. 关于UITableView的Cell复用谈谈我的一些心得滴水穿石
  20. 【Java编程】创建人类Person

热门文章

  1. WPS表格Excel:提取批注到单元格(宏实现)
  2. 王哲在腾讯 GAD《论道》栏目组的视频访谈
  3. mysql 批量replace into_replace into 批量更新
  4. 网易杭州研发中心-算法工程师面经
  5. 移动端调试工具vConsole与Eruda
  6. PDF怎么转换为CAD?这里有个好用的方法
  7. 基于Java的网络兼职平台系统的设计与实现(论文+程序设计+数据库文件)
  8. SQL Server:使用T-SQL创建视图
  9. 浅析闪存盘(Flash Drive)内部架构与应用考虑
  10. 传奇人物《周兴和》书连载之67 不辱神圣的使命