当前位置: 首页 > news >正文

React Hooks中使用useState异步回调获取不到最新值的问题

ReactHook中useState异步回调获取不到最新值及解决⽅案

预先了解 setState 的两种传参⽅式

1、直接传⼊新值 setState(options);

列如:

const [state, setState] = useState(0);

setState(state + 1);

2、传⼊回调函数 setState(callBack);

例如:

const [state, setState] = useState(0);

setState((prevState) => prevState + 1); // prevState 是改变之前的 state 值,return 返回的值会作为新状态覆盖 state 值

useState 异步回调获取不到最新值及解决⽅案

通常情况下 setState 直接使⽤上述第⼀种⽅式传参即可,但在⼀些特殊情况下第⼀种⽅式会出现异常;

例如希望在异步回调或闭包中获取最新状态并设置状态,此时第⼀种⽅式获取的状态不是实时的,React 官⽅⽂档提到:组件内部的任何函数,包括事件处理函数和 Effect,都是从它被创建的那次渲染中被「看到」的,所以引⽤的值任然是旧的,最后导致 setState 出现异常:

import React, { useState, useEffect } from 'react';

const App = () => {

const [arr, setArr] = useState([0]);

useEffect(() => {

console.log(arr);

}, [arr]);

const handleClick = () => {

Promise.resolve().then(() => {

setArr([...arr, 1]); // 此时赋值前 arr 为:[0]

})

.then(() => {

setArr([...arr, 2]); // 此时赋值前 arr 为旧状态仍然为:[0]

});

}

return (

<>

<button onClick={handleClick}>change</button>

</>

);

}

export default App;

上⾯代码,App 组件实际也是个闭包函数,handleClick ⾥⾯引⽤着 arr,第⼀次 setArr 后 arr 的值确实更新了,我们也可以在下⾯截图中看到,但此次执⾏的 handleClick 事件处理函数作⽤域还是旧的,⾥⾯引⽤的 arr 仍然为旧的,导致第⼆次 setArr 后结果为 [0, 2]:

在 class 组件中我们可以使⽤ setState(options, callBack); 在 setState 的第⼆个参数回调函数中再次进⾏ setState,也不存在闭包作⽤域问题,但是 React Hook 中 useState 移除了 setState 的第⼆个参数,⽽且若嵌套太多也不佳;

解决⽅案1(推荐使⽤):

将上述代码使⽤第⼆种(回调)⽅式传参

const handleClick = () => {

Promise.resolve().then(() => {

setArr(prevState => [...prevState, 1]); // 这⾥也可以不改,使⽤第⼀中传参⽅式 setArr([...arr, 1]); 因为这⾥不需要获取最新状态

})

.then(() => {

setArr(prevState => [...prevState, 2]); // 这⾥必须改成回调函数传参⽅式,否则会读取旧状态,导致异常

});

}

解决⽅案2:

使⽤ useReducer 仿造类组件中的 forceUpdate 实现组件强制渲染;

import React, { useState, useReducer } from 'react';

const App = () => {

const [arr, setArr] = useState([0]);

const [, forceUpdate] = useReducer(x => x + 1, 0);

const handleClick = () => {

Promise.resolve().then(() => {

arr.push(1); // 如果这⾥也需要做⼀次渲染在改变状态后调⽤ forceUpdate() 即可 })

.then(() => {

arr.push(2);

forceUpdate();

});

}

return (

<>

<h1>{arr.toString()}</h1>

<button onClick={handleClick}>change</button>

</>

);

}

export default App;

点击前:

点击后:

解决⽅案3:

利⽤ ref

import React, { useState, useRef, useEffect } from 'react';

const App = () => {

const [arr, setArr] = useState([0]);

let ref = useRef();

useEffect(() => {

ref.current = arr;

console.log(arr);

});

const handleClick = () => {

Promise.resolve().then(() => {

const now = [...ref.current, 1];

ref.current = now;

setArr(now);

})

.then(() => {

setArr([...ref.current, 2]);

});

}

return (

<>

<h1>{arr.toString()}</h1>

<button onClick={handleClick}>change</button>

</>

);

}

export default App;

相关文章:

React Hooks中使用useState异步回调获取不到最新值的问题

ReactHook中useState异步回调获取不到最新值及解决⽅案 预先了解 setState 的两种传参⽅式 1、直接传⼊新值 setState(options); 列如&#xff1a; const [state, setState] useState(0); setState(state 1); 2、传⼊回调函数 setState(callBack); 例如&#xff1a; …...

JavaScript 高级 (完结)

目录 深浅拷贝 浅拷贝 深拷贝 递归实现深拷贝 js库lodash里面cloneDeep内部实现了深拷贝 JSON序列化 异常处理 throw 抛异常 try /catch 捕获异常 debugg 处理this this指向 普通函数 箭头函数 改变this call() apply() bind() call apply bind 总结 性能优化…...

【P30】JMeter 事务控制器(Transaction Controller)

文章目录 一、事务控制器&#xff08;Transaction Controller&#xff09;参数说明二、测试计划设计2.2.1、勾选 Generate parent sample2.2.1、勾选 Include duration of timer and pre-post processors in generated sample 一、事务控制器&#xff08;Transaction Controlle…...

【MySQL】MySQL的事务原理和实现?

文章目录 MySQL事务的底层实现原理一、事务的目的可靠性和并发处理 二、实现事务功能的三个技术2.1 redo log 与 undo log介绍2.1.1 redo log2.1.2undo log 2.2 mysql锁技术2.2.1 mysql锁技术 2.3 MVCC基础 三、事务的实现3.1 原子性的实现3.1.1 undo log 的生成3.1.2 根据undo…...

S7-300Smart1200的ISO on TCP通信

1、西门子PLC的通信资源 1.1 S7-1200 的PROFINET 通信口 S7-1200 CPU 本体上集成了一个 PROFINET 通信口,支持以太网和基于 TCP/IP 的通信标准。使用这个通信口可以实现 S7-1200 CPU 与编程设备的通信,与HMI触摸屏的通信,以及与其它 CPU 之间的通信。这个PROFINET 物理接口…...

Spark写入Hive报错Mkdir failed on :com.alibaba.jfs.JindoRequestPath

1. 报错内容 23/05/31 14:32:13 INFO [Driver] FsStats: cmdmkdirs, srcoss://sync-to-bi.[马赛克].aliyuncs.com/tmp/hive, dstnull, size0, parameterFsPermission:rwx-wx-wx, time-in-ms32, version3.5.0 23/05/31 14:32:13 ERROR [Driver] ApplicationMaster: User class …...

分布式id解决方法--雪花算法

uuid&#xff0c;jdk自带&#xff0c;但是数据库性能差&#xff0c;32位呀。 mysql数据库主键越短越好&#xff0c;Btree产生节点分裂&#xff0c;大大降低数据库性能&#xff0c;所以uuid不建议。 redis的自增&#xff0c;但是要配置维护redis集群&#xff0c;就为了一个id&a…...

5年经验之谈:月薪3000到30000,测试工程师的变“行”记

自我介绍下&#xff0c;我是一名转IT测试人&#xff0c;我的专业是化学&#xff0c;去化工厂实习才发现这专业的坑人之处&#xff0c;化学试剂害人不浅&#xff0c;有毒&#xff0c;易燃易爆&#xff0c;实验室经常用丙酮&#xff0c;甲醇&#xff0c;四氯化碳&#xff0c;接触…...

PMP考试都是什么题?

PMP新版大纲加入了ACP敏捷管理的内容&#xff0c;说是敏捷混合题型占到了 50%&#xff0c;但是这次318的考试&#xff0c;敏捷题占了大半&#xff0c;都说敏捷和情景快要占到80%-90%。 所以有友友说开了四个小时盲盒&#xff0c;题目读不懂&#xff0c;或者觉得4个选项都不对或…...

macbook2023系统清理软件cleanmymac中文版

cleanmymac x 中文版基本都是大家首选Mac清理软件了。它集各种功能于一身&#xff0c;几乎满足用户所有的清理需求。它可以清理&#xff0c;优化&#xff0c;保养和监测您的电脑&#xff0c;确保您的Mac运行畅通无阻&#xff01;支持一键快速清理Mac&#xff0c;快速检查并安全…...

基于Python+AIML+Tornado的智能聊天机器人(NLP+深度学习)含全部工程源码+语料库 适合个人二次开发

目录 前言总体设计系统整体结构图系统流程图 运行环境Python 环境Tornado 环境 模块实现1. 前端2. 后端3. 语料库4. 系统测试 其它资料下载 前言 本项目旨在利用AIML技术构建一个聊天机器人&#xff0c;实现用户通过聊天界面与机器人交互的功能。通过提供的工程源代码&#xf…...

算法Day15 | 层序遍历,102,107,199,637,429,515,116,117,104,111,226,101

Day15 层序遍历102.二叉树的层序遍历107.二叉树的层次遍历 II199.二叉树的右视图637.二叉树的层平均值429.N叉树的层序遍历515.在每个树行中找最大值116.填充每个节点的下一个右侧节点指针117.填充每个节点的下一个右侧节点指针II104.二叉树的最大深度111.二叉树的最小深度 226…...

Prometheus+Grafana学习(十一)安装使用pushgateway

Pushgateway允许短暂和批量作业将其指标暴露给 Prometheus。由于这些工作的生命周期可能不足够长&#xff0c;不能够存在足够的时间以让 Prometheus 抓取它们的指标。Pushgateway 允许它们可以将其指标推送到 Pushgateway&#xff0c;然后 Pushgateway 再将这些指标暴露给 Prom…...

深入理解C/C++预处理器指令#pragma once以及与ifndef的比较

#pragma once用法总结 为了防止重复引用造成二义性 在C/C中&#xff0c;在使用预编译指令#include的时候&#xff0c;为了防止重复引用造成二义性&#xff0c;通常有两种方式 第一种是#ifndef指令防止代码块重复引用&#xff0c;比如说 #ifndef _CODE_BLOCK #define _CODE_BLO…...

git 环境配置 + gitee拉取代码

好嘛 配环境的时候 老是忘记这个命令行 干脆自己写一个记录一下 也不用搜了 1.先从git官网下载git 安装 2.然后从gitee拉取代码的时候提示 这是因为换了新电脑没有加入新的公钥啦 哎 所以老是记不住命令行 first &#xff1a; git config --global user.name “Your Name” …...

港联证券|港股拥抱特专科技企业 内资券商“修炼内功”蓄势而为

港股市场新一轮改革举措渐次落地。特别是港交所推出特专科技公司上市机制&#xff0c;吸引符合资格的科技企业申请赴港上市&#xff0c;成为这一轮港股市场改革的“重头戏”。 作为香港资本市场的重要参与者&#xff0c;内资券商立足香港、背靠内地、辐射全球&#xff0c;走出一…...

多项创新技术加持,实现零COGS的Microsoft Editor语法检查器

编者按&#xff1a;Microsoft Editor 是一款人工智能写作辅助工具&#xff0c;其中的语法检查器&#xff08;grammar checker&#xff09;功能不仅可以帮助不同水平、领域的用户在写作过程中检查语法错误&#xff0c;还可以对错误进行解释并给出正确的修改建议。神经语法检查器…...

Python编程环境搭建:Windows中如何安装Python

在 Windows 上安装 Python 和安装普通软件一样简单&#xff0c;下载安装包以后猛击“下一步”即可。 Python 安装包下载地址&#xff1a;https://www.python.org/downloads/ 打开该链接&#xff0c;可以看到有两个版本的 Python&#xff0c;分别是 Python 3.x 和 Python 2.x&…...

Sui Builder House首尔站倒计时!

Sui主网上线后的第一场Builder House活动即将在韩国首尔举行&#xff0c;同期将举办首场线下面对面的黑客松。活动历时两天&#xff0c;将为与会者提供独特的学习、交流和娱乐的机会。活动详情请查看&#xff1a;Sui Builder House首尔站&#xff5c;主网上线后首次亮相。 Sui…...

Java设计模式-状态模式

简介 在软件开发领域&#xff0c;设计模式是一组经过验证的、被广泛接受的解决问题的方案。其中之一是状态模式&#xff0c;它提供了一种优雅的方式来管理对象的不同状态。 状态模式是一种行为型设计模式&#xff0c;它允许对象在内部状态发生改变时改变其行为。状态模式将对…...

智慧社区用什么技术开发

智慧社区是指利用信息技术和先进的管理理念&#xff0c;将社区内的各种公共服务进行整合和优化&#xff0c;提高社区居民的生活品质和社区管理的效率。为了实现智慧社区的建设&#xff0c;需要采用多种技术&#xff0c;包括但不限于以下几种&#xff1a; 1.物联网技术&#xf…...

多线程 线程池饱和策略

RejectedExecutionHandler&#xff08;饱和策略&#xff09;&#xff1a;当队列和线程池都满了&#xff0c;说明线程池处于饱和状态&#xff0c;那么必须采取一种策略处理提交的新任务。 这个策略默认情况下是AbortPolicy&#xff0c;表示无法处理新任务时抛出异常。 在JDK 1…...

进程间通信之信号

进程间通信之信号 1. 信号2. 信号由谁产生?3. 有哪些信号4. 信号的安装5. 信号的发送1) 使用kill函数2)使用alarm函数3) 使用raise6.发送多个信号7. 信号集1. 信号 什么是信号? 信号是给程序提供一种可以处理异步事件的方法,它利用软件中断来实现。不能自定义信号,所有信号…...

二分查找三道题

二分查找 两种写法&#xff1a;左闭右闭[left,right]、左闭右开[left,right) 主要有几点不同&#xff1a;1. right是从num.length开始还是从num.length-1开始。2.left<还是<right。3.rightmid还是mid1 左闭右闭写法&#xff1a; public int search(int[] nums, int targ…...

MyBatis 框架

MyBatis 框架 MyBatis 简介搭建 MyBatis 开发环境核心配置文件详解mapper 映射文件&#xff08;实现增删改查&#xff09;MyBatis获取参数值的两种方式MyBatis的各种查询功能特殊SQL的执行自定义映射resultMapresultMap 字段和属性的映射多对一映射处理一对多映射处理 动态SQLM…...

【C++】虚表和虚基表到底有哪些区别?

虚表和虚基表 虚表虚基表虚拟继承和虚函数都存在时的对象模型 虚表 我们知道&#xff0c;如果类中声明了的方法是用virtual进行修饰的&#xff0c;则说明当前这个方法要作为虚函数&#xff0c;而虚函数的存储和普通函数的存储是有区别的 当有虚函数声明时&#xff0c;编译器会…...

剑指 Offer 04. 二维数组中的查找解题思路

文章目录 标题解题思路优化 标题 在一个 n * m 的二维数组中&#xff0c;每一行都按照从左到右 非递减 的顺序排序&#xff0c;每一列都按照从上到下 非递减 的顺序排序。请完成一个高效的函数&#xff0c;输入这样的一个二维数组和一个整数&#xff0c;判断数组中是否含有该整…...

冯诺依曼体系结构详解

一.冯诺伊曼体系结构的概念&#xff1a; 约翰冯诺依曼&#xff08;John von Neumann&#xff0c;1903.1.28-1957.2.8&#xff09;&#xff0c;美籍匈牙利数学家&#xff0c;计算机科学家&#xff0c;物理学家。是20世纪最重要的数学家之一&#xff0c;后来被称为计算机之父。 后…...

ISO证书“带标”与“不带标”的区别是什么?

ISO9001质量管理体系认证是企业产品获得“通行绿卡”的最直接最有效的途径。 通过认证在打破贸易壁垒&#xff0c;提高产品知名度&#xff0c;降低生产成本&#xff0c;提高经济效益&#xff0c;维护消费者权益&#xff0c;减少重复审核负担等方面的作用越来越为企业界所共知。…...

RocketMQ 领域模型概述

本文为您介绍 Apache RocketMQ 的领域模型。 Apache RocketMQ 是一款典型的分布式架构下的中间件产品&#xff0c;使用异步通信方式和发布订阅的消息传输模型。通信方式和传输模型的具体说明&#xff0c;请参见下文通信方式介绍和消息传输模型介绍。 Apache RocketMQ 产品具备…...