setState函数是异步的还是同步的?
setState函数是异步的还是同步的?
可能很多同学在看到这个问题的时候,甚至搞不清楚这个问题在问什么。
不要慌,我们看一下下面这个例子,首先我们创建一个类组件,这个类组件中,我们定义了state是一个对象,对象中有一个属性为count,count的初始值为0,再页面中,设置了一个h2标签,标签显示count的值,同时添加了一个button按钮,每次点击按钮,使用setState对count进行+1,同时输出当前count的值:
class Example extends React.Component {constructor(props) {super(props);this.state = {count: 0};}render() {return (<div><h2>count: {this.state.count}.</h2><button onClick={()=>{this.setState({count:this.state.count+1});console.log("count",this.state.count);}}></button></div>);}}
运行之后,大家可以尝试一下,点击按钮之后,count在页面中会显示count:1,但是控制台console.log输出的是0;再点击一次,count在页面中会显示count:2,但是控制台console.log输出的是1;不管我们点击多少次,情况一直是这样。
但是从代码的角度上来说,点击之后setState起作用,这个时候console出来的state应该是最新的state才对,但是输出结果却不是这样的,console.log中没有同步更新数据,所以,我们认为:setState是异步处理数据变化的
这句话怎么理解呢?
首先我们来看一下setState的定义,setState接受一个带有形式参数的 updater 函数(也可能直接是一个对象)与一个回调callback(可选)。
setState(updater, [callback])
官方明确表示,setState对于this.state并不是立刻更新,若在调用setState后想要立刻获取到最新的this.state,那么建议在setState的callback或者声明周期componentDidUpdate中获取
所以,如果立即想获得setState更新后的数据,可以写在callback中:
class Example extends React.Component {constructor(props) {super(props);this.state = {count: 0};}render() {return (<div><h2>count: {this.state.count}.</h2><button onClick={()=>{this.setState({count:this.state.count+1},()=>{console.log("count",this.state.count);});}}></button></div>);}}
这个时候,我们运行后就能发现,我们能立马获得setState更新后的数据。
回到我们刚开始的问题,setState是同步的还是异步的,用一句话概括就是:
异步更新,同步执行,setState函数本身并不是异步的,但是对state的处理机制给人一种异步的假象,state处理一般发生在生命周期发生变化的时候;
为什么官方要这样去设置呢,我们继续深挖一下,依然是上面的代码,但是click函数中setState函数调用了两次:
class Example extends React.Component {constructor(props) {super(props);this.state = {count: 0};}render() {return (<div><h2>count: {this.state.count}.</h2><button onClick={()=>{this.setState({count:this.state.count+1},()=>{console.log("count",this.state.count);});this.setState({count:this.state.count+1},()=>{console.log("count",this.state.count);});}}></button></div>);}}
当点击按钮,我们需要连着两次执行setState,那么react会帮我们修改两次this.state然后重新render两次吗?很明显并不是,react会批量合并多次setState操作,上述例子num最终是2,且render在点击后只会渲染一次。
也就是我们所说的,只有生命周期发生变化,state才会变化,否则this.state一直拿到的就是上一次渲染后的。
React在开始重新渲染之前, 会有意地进行"等待",直到所有在组件的事件处理函数内调用的 setState()都完成之后再做最终的this.state变更,这样可以通过避免不必要的重新渲染来提升性能。
那么,如果我们的目的,就是想让他连着更新两次呢?该怎么修改这段代码呢?
前面我们讲了setState的定义setState(updater, [callback]),第一个参数updater除了可以是对象,还可以是函数,写成函数就可以解决这个问题了:
class Example extends React.Component {constructor(props) {super(props);this.state = {count: 0};}render() {return (<div><h2>count: {this.state.count}.</h2><button onClick={()=>{//这里函数里的参数的prestate和preprops都是最新更改的上一次的state和propsthis.setState((prestate,preprops)=>{return {count:pre.count+1}},()=>{console.log("count",this.state.count);});this.setState((prestate,preprops)=>{return {count:pre.count+1}},()=>{console.log("count",this.state.count);});}}></button></div>);}}
这样我们发现,当我们点击按钮,页面的count和终端的count都每次增加2了
相关文章:
setState函数是异步的还是同步的?
setState函数是异步的还是同步的? 可能很多同学在看到这个问题的时候,甚至搞不清楚这个问题在问什么。 不要慌,我们看一下下面这个例子,首先我们创建一个类组件,这个类组件中,我们定义了state是一个对象,对象中有一个…...
vue3+ts:约定式提交(git husky + gitHooks)
一、背景 Git - githooks Documentation https://github.com/typicode/husky#readme gitHooks: commit-msg_snowli的博客-CSDN博客 之前实践过这个配置,本文在vue3 ts 的项目中,再记录一次。 二、使用 2.1、安装 2.1.1、安装husky pnpm add hus…...
TSP 问题求解的最好方法 LKH
目前可以查到的最好的方法求解TSP问题是 LKH,所以本篇文章介绍如何使用Matlab 调用LKH 参考文档:用matlab调用迄今为止最强悍的求解旅行商(TSP)的算法-LKH算法_wx6333e948c3602的技术博客_51CTO博客 【LKH算法体验】用matlab调用…...
RocketMQ5.1控制台的安装与启动
RocketMQ控制台的安装与启动下载修改配置开放端口号重启防火墙添加依赖编译 rocketmq-dashboard运行 rocketmq-dashboard本地访问rocketmq无法发送消息失败问题。connect to <公网ip:10911> failed下载 下载地址 修改配置 修改其src/main/resources中…...
【java基础】类型擦除、桥方法、泛型代码和虚拟机
文章目录基础说明类型擦除无限定有限定转换泛型表达式方法类型擦除(桥方法)关于重载的一些说明总结基础说明 虚拟机没有泛型类型对象一所有对象都属于普通类。在泛型实现的早期版本中,甚至能够将使用泛型的程序编译为在1.0虚拟机上运行的类文…...
十家公司有九家问过的软件测试面试题,最后一题我猜你肯定不会
最近面试了一些测试方面相关的岗位,通过牛客等途径也看了不少的面经,发现大部分人面试题目都有很多相似点,结合自己的一些面试经历,现在分享一些我面试中碰到过的问题 常见的面试题 1、jmeter的加密参数如何入参? 2…...
C++核心知识(三)—— 静态成员(变量、函数、const成员)、面向对象模型(this指针、常函数、常对象)、友元、数组类、单例模式
【上一篇】C核心知识(二)—— 类和对象(类的封装)、对象的构造和析构(浅拷贝、深拷贝、explicit、动态分配内存)1. 静态成员在类定义中,它的成员(包括成员变量和成员函数),这些成员可以用关键字static声明为…...
RocketMQ【3】Rocketmq集群部署(多master多slave)异步复制
系列文章目录 RocketMQ【1】linux安装配置Rocketmq(单机版) RocketMQ【2】Rocketmq控制台安装启动(单机版) 文章目录系列文章目录一、异步复制的优缺点1、优点2、缺点二、架构1、架构图2、介绍3、机器配置三、配置1、master节点配…...
魏玛早春 木心
<font face“黑体” color#CD5C5C size6 魏玛早春 木心 温带每个季节之初 总有神圣气象恬漠地 剀切地透露在风中 冬天行将退尽 春寒嫩生生 料峭而滋润 漾起离合纷纷的私淑记忆 日复一日 默认季节的更替 以春的正式最为谨慎隆重 如果骤尔明暖 鸟雀疏狂飞鸣 必定会吝悔似的剧…...
关于Scipy的概念和使用方法及实战
关于scipy的概念和使用方法 什么是Scipy Scipy是一个基于Python的科学计算库,它提供了许多用于数学、科学、工程和技术计算的工具和函数。Scipy的名称是“Scientific Python”的缩写。 Scipy包含了许多子模块,其中一些主要的子模块包括: …...
第二章Linux操作语法1
文章目录vi和vim常用的三种模式vi和vim快捷键Linux开机,重启用户管理用户信息查询管理who和whoami用户组信息查询管理用户和组的相关文件实用指令集合运行级别帮助指令manhelp文件管理类pwd命令ls命令cd命令mkdir命令rmdir命令rm命令touch命令cp指令mv指令文件查看类…...
linux内核调度问题分析
目录 一、调度场景分析 不支持内核抢占的内核 支持内核抢占 二、如何让新进程执行 三、调度的本质 一、调度场景分析 假如内核只有3个线程,线程0创建线程1和线程2.当系统时钟到来时,时钟中断处理函数会检查是否有进程需要调度。当有进程需要调度时…...
C语言-基础了解-25-C强制类型转换
C强制类型转换 一、强制类型转换 强制类型转换是把变量从一种类型转换为另一种数据类型。例如,如果您想存储一个 long 类型的值到一个简单的整型中,您需要把 long 类型强制转换为 int 类型。您可以使用强制类型转换运算符来把值显式地从一种类型转换为…...
【Python】如何安装 Allure 工具进行自动化测试
Allure 是一种流行的工具,用于以人类可读的格式生成测试报告,从而更容易理解和分析测试结果。在这篇博客中,我们将探索如何在 Windows 机器上安装 Allure 及其依赖项。 1 Prerequisites 先决条件 在田辛老师开始之前,请确保您的…...
nginx七大核心应用场景详解 解决生产中的实际问题 二次开发扩展
nginx七大核心应用场景详解 & 解决生产中的实际问题1、nginx的安装与简单配置1.1、环境准备1.2、nginx基本操作指令:1.3、安装成系统服务1.4、conf 配置文件说明2、虚拟主机2.1、nginx多主机配置2.2、二级域名与短网址解析3、基于反向代理的负载均衡3.1、跳转到…...
Java 整合 Redis
文章目录Java 整合 Redis一、Jedis二、Spring-Data-RedisJava 整合 Redis Redis 在项目中我们主要用来做缓存,就像我们用 MySQL 做持久层数据一样。Redis 的客户端有两种实现方式: 一是直接调用 Jedis 来实现,类似于 Java 使用 JDBC 操作数…...
Django实践-03模型-02基于admin管理表
文章目录Django实践-03模型利用Django后台管理模型1. 将admin应用所需的表迁移到数据库中。2. 创建访问admin应用的超级用户账号,3. 运行项目4.注册模型类5.对模型进行CRUD操作。6.实现学科页和老师页效果1. 修改polls/views.py文件。2.修改templates/polls/subject…...
如何安装python
windows安装 下载安装包 登录python官网 https://www.python.org/ 点击downloads 置顶下载的是最新的python版本 如果想下载指定版本往下翻找 安装程序 点击即可下载,然后打开下载的exe程序 勾选添加pythonexec到path,也就是添加到环境变量 使用a…...
java String类 万字详解(通俗易懂)
目录 一、前言 二、介绍和溯源 三、String类常用构造器 1.String() 2.String(byte[] bytes) 3.String(char[] value) 4.String(char[] value, int offset, int count) 5.String(String original) Δ演示 : 四、不同方式创建String类对象的区别 1.直接赋值的方式 2.常规new…...
Hive拉链表
概述 拉链表:维护历史状态以及最新状态数据的表 作用场景 1. 数据量比较大。 2. 表中的部分字段会被更新,比如用户的地址,银行利率,订单的状态等。 3. 需要查看某一个时间点或者时间段的历史快照信息,比如,…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...
Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...
MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...
Docker拉取MySQL后数据库连接失败的解决方案
在使用Docker部署MySQL时,拉取并启动容器后,有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致,包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因,并提供解决方案。 一、确认MySQL容器的运行状态 …...
