react中的setState详解
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详解相关推荐
- js路由在php上面使用,React中路由使用详解
这次给大家带来React中路由使用详解,React中路由使用的注意事项有哪些,下面就是实战案例,一起来看一下. 路由 通过 URL 映射到对应的功能实现,React 的路由使用要先引入 react-r ...
- React中使用Vditor详解(自定义图片)
安装 npm install vditor -s 引用 导入依赖包 import Vditor from "vditor"; 导入样式 import "vditor/sr ...
- React中的Hooks详解
1.概述 React官方网站原文:Hooks 是一项新功能提案,可让您在不编写类的情况下使用 state(状态) 和其他 React 功能. 我总结了下使用Hooks的理由: 1.解决class中的代 ...
- react中的state详解
state 理解:state是组件对象最重要的属性,值是对象(可以包含多个key-value组合) state中的值可以修改,修改的唯一方法是调用this.setState,每次修改以后,自动调用 t ...
- webpack搭建php服务器,webpack搭建react开发环境步骤详解
这次给大家带来webpack搭建react开发环境步骤详解,webpack搭建react开发环境的注意事项有哪些,下面就是实战案例,一起来看一下.mkdir react-redux && ...
- ALSA声卡驱动中的DAPM详解之四:在驱动程序中初始化并注册widget和route
前几篇文章我们从dapm的数据结构入手,了解了代表音频控件的widget,代表连接路径的route以及用于连接两个widget的path.之前都是一些概念的讲解以及对数据结构中各个字段的说明,从本章开 ...
- Asp.net中GridView使用详解(引)【转】
Asp.net中GridView使用详解(引) GridView无代码分页排序 GridView选中,编辑,取消,删除 GridView正反双向排序 GridView和下拉菜单DropDownList ...
- Linux中iptraf命令详解(IP局域网监控工具)
2019独角兽企业重金招聘Python工程师标准>>> Linux中iptraf命令详解(IP局域网监控工具) 发布时间:2017-12-27 20:46:03 作者:佚名 ...
- ArcGIS Engine中的Symbols详解
转自原文 ArcGIS Engine中的Symbols详解 本文由本人翻译ESRI官方帮助文档.尊重劳动成果,转载请注明来源. Symbols ArcObjects用了三种类型的Symbol(符号样式 ...
最新文章
- “元宇宙”数字化理解
- 计算机二级find,Excel函数-find、if和iferror-计算机二级Office
- dao层通用封装_DAO层–救援通用
- 中国联通董事李福申辞任
- mysql my.ini配置优化_求高手帮我优化一下 mysql 的 my.ini
- theadClasses设置Bootstrap Table表头样式
- html搜索联系人,联系人列表.html
- java 不支持,不支持Java Sound格式
- CEF3 C++接口实现自定义浏览器[simple version]
- 订单拆单-产品逻辑分析研究
- 武汉青少年计算机编程,武汉青少年编程学习
- AMADA阿玛达工控机维修折弯机主机维修R027-00主板故障处理
- SAS系统学习之初探
- 用Python做雷霆战机小游戏【附素材+源码】
- 穆帅战巴萨督编励志片 内含梅西踢皇马球迷皮克5指山
- yy账号找回方法详解
- 程序员的悲哀--动车追尾
- 上线两个月,微信小程序给那些用身体支持它的人带来了什么?
- 关于UITableView的Cell复用谈谈我的一些心得滴水穿石
- 【Java编程】创建人类Person