React state 更新时机以及强制更新

设置 state 只会为下一次渲染变更 state 的值
一个 state 变量的值永远不会在一次渲染的内部发生变化
React 会使 state 的值始终"固定"在一次渲染的各个事件处理函数内部
React 会等到事件处理函数中的所有代码都运行完毕再处理 state 更新
用 flushSync 可以同步更新 state

  1. 在一个函数中,多次设置state, 最终结果由最后一次决定
export default function Counter() {const [number, setNumber] = useState(0);return (<><h1>{number}</h1><button onClick={() => {// 第一次执行时,number为0setNumber(number + 1); // 相当于setNumber(0 + 1),React 准备在下一次渲染时将 number 更改为 1,React 将 “替换为 1” 添加到其队列中。setNumber(number + 1); // 相当于setNumber(0 + 1),React 准备在下一次渲染时将 number 更改为 1,React 将 “替换为 1” 添加到其队列中。setNumber(number + 1); // 相当于setNumber(0 + 1),React 准备在下一次渲染时将 number 更改为 1,React 将 “替换为 1” 添加到其队列中。// 执行结果 number = 1}}>+3</button></>)
}
  1. 即使事件处理函数的代码是异步的,它获取到的state也是与本次最初执行时的值保持一致的,state在一次执行时不会改变。
export default function Counter() {const [number, setNumber] = useState(0);return (<><h1>{number}</h1><button onClick={() => {setNumber(number + 5);setTimeout(() => {alert(number); // 0 在onClick执行时,number的值就被固定了。state 在“获取 UI 的快照”时就被“固定”了}, 3000);}}>+5</button></>)
}

如何在重新渲染前,多次更新同一个state

setNumber(n => n + 1)
通过传入一个更新函数 n=>n+1来更新state的值

export default function Counter() {const [number, setNumber] = useState(0);return (<><h1>{number}</h1><button onClick={() => {setNumber(n => n + 1); // n => n + 1 是一个函数。React 将它加入队列。setNumber(n => n + 1); // n => n + 1 是一个函数。React 将它加入队列。setNumber(n => n + 1); // n => n + 1 是一个函数。React 将它加入队列。}}>+3</button></>)
}

当在下次渲染期间调用 useState 时,React 会遍历队列。 之前的 state 的值是 0,所以这就是 React 作为参数 n 传递给第一个更新函数的值。然后 React 会获取上一个更新函数的返回值,并将其作为 n 传递给下一个更新函数,以此类推:

更新队列n返回值
n => n + 100 + 1 = 1
n => n + 111 + 1 = 2
n => n + 122 + 1 = 3

React 会保存 3 为最终结果并从 useState 中返回。

用 flushSync 同步更新 state

flushSync ,强制 React 同步更新(“刷新”)DOM ,类似与 $nextTick 。

// 自动滚至新添加的元素位置
// 当 flushSync 中的代码执行后,立即同步更新 DOM。因此,滚动到最后一个待办事项时,它已经在 DOM 中了
import { useState, useRef } from 'react';
import { flushSync } from 'react-dom';let nextId = 0;export default function TodoList() {const listRef = useRef(null);const [text, setText] = useState('');const [todos, setTodos] = useState([]);function handleAdd() {const newTodo = { id: nextId++, text: text };flushSync(() => {setText('');setTodos([ ...todos, newTodo]);      });listRef.current.lastChild.scrollIntoView({behavior: 'smooth',block: 'nearest'});}return (<><button onClick={handleAdd}>添加</button><inputvalue={text}onChange={e => setText(e.target.value)}/><ul ref={listRef}>{todos.map(todo => (<li key={todo.id}>{todo.text}</li>))}</ul></>);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/31188.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PostgreSQL查询用户

在 PostgreSQL 中&#xff0c;可以通过查询系统表来确定当前用户是否是超级管理员&#xff08;超级用户&#xff09;。具体来说&#xff0c;可以使用 pg_roles 系统表&#xff0c;该表包含数据库中所有角色的信息。 以下是查询当前用户是否是超级用户的 SQL 语句&#xff1a; …

第N5周:调用Gensim库训练Word2Vec模型

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制&#x1f680; 文章来源&#xff1a;K同学的学习圈子 目录 本周任务: 1.安装Gensim库 2.对原始语料分词 3.停用词 4.训练Woed2Vec模型 …

办展览如何盈利?论办展的商业模式

想要弄清楚办展览怎么赚钱这个问题&#xff0c;我可以来说说。 首先来说说展览收益的大头&#xff1a;门票收入。 这个其实是可以大致预测的。简单来说&#xff0c;就是用流量乘以到店率。 但别忘了&#xff0c;这背后得有合适的展览定位、方便的展览场地和合理的票价。 说…

封禁SSH登录的IP

在公网上开放SSHD服务时常被黑客扫描&#xff0c;可用以下方式封禁其IP&#xff1a; 1. 在/etc/hosts/deny中加&#xff1a;sshd: /etc/sshd.deny.hostguard echo "sshd: /etc/sshd.deny.hostguard" > /etc/hosts/deny 2. 然后将/var/log/secure中探测密码的远…

小林图解系统-三、操作系统结构

Linux 内核 vs Windows 内核 内核 作为应用连接硬件设备的桥梁&#xff0c;保证应用程序只需要关心与内核交互&#xff0c;不需要关心硬件的细节 内核具备四个基本能力&#xff1a; 管理进程、线程&#xff0c;决定哪个进程、线程使用CPU&#xff0c;也就是进程调度的能力&a…

Linux——ansible关于“文件操作”的模块

修改文件并将其复制到主机 一、确保受管主机上存在文件 使用 file 模块处理受管主机上的文件。其工作方式与 touch 命令类似&#xff0c;如果不存在则创建一个空文件&#xff0c;如果存在&#xff0c;则更新其修改时间。在本例中&#xff0c;除了处理文件之外&#xff0c;Ansi…

华为设备SSH远程访问配置实验简述

一、实验需求: 1、AR1模拟电脑SSH 访问AR2路由器。 二、实验步骤&#xff1a; 1、AR1和AR2接口配置IP&#xff0c;实现链路通信。 2、AR2配置AAA模式 配置用户及密码 配置用户访问级别 配置用户SSH 访问服务 AR2配置远程服务数量 配置用户远程访问模式为AAA 配置允许登录接入用…

【问题记录】Ubuntu提示: “E: 软件包 gcc 没有可安装候选“

Ubuntu提示: "E: 软件包 gcc 没有可安装候选" 一&#xff0c;问题现象二&#xff0c;问题原因&解决方法 一&#xff0c;问题现象 在虚拟机Ubuntu中进行安装gcc命令时报错&#xff1a;“E: 软件包 gcc 没有可安装候选”: 二&#xff0c;问题原因&解决方法 …

go-zero使用goctl生成mongodb的操作使用方法

目录 MongoDB简介 MongoDB的优势 对比mysql的操作 goctl的mongodb代码生成 如何使用 go-zero中mogodb使用 mongodb官方驱动使用 model模型的方式使用 其他资源 MongoDB简介 mongodb是一种高性能、开源、文档型的nosql数据库&#xff0c;被广泛应用于web应用、大数据以…

刷题——寻找峰值

寻找峰值_牛客题霸_牛客网 int findPeakElement(vector<int>& nums) {// write code hereint left 0, right nums.size() - 1;while(left < right){int mid (right - left) / 2 left;if(nums[mid] < nums[mid 1])left mid 1;elseright mid;}return lef…

Linux grep -r 遍历包括子文件内容和 jar包的类

grep -r 遍历包括子文件内容和 jar包的类 (base) [roottest002 24-06-20 13:38:47 flink-cdc-3.1.0 #] grep -r com.mysql.cj.jdbc.Driver * 匹配到二进制文件 lib/mysql-connector-java-8.0.27.jar (base) [roottest002 24-06-20 13:41:32 flink-cdc-3.1.0 #] vim 1 (base) [r…

性能测试-性能监控分析与调优(三)《实战》

性能监控 使用命令监控 cpu瓶颈分析 top命令 在进行性能测试时使用top命令&#xff0c;界面如下 上图可以看出 CPU 概况区&#xff1a; %Cpu(s): us&#xff08;用户进程占用CPU的百分比&#xff09;, 和 sy&#xff08;系统进程占用CPU的百分比&#xff09; 的数值很高…

FreeRTOS学习 -- 队列

一、队列简介 队列是为了任务与任务、任务与中断之间的通信而准备的&#xff0c;可以在任务与任务、任务与中断之间传递消息&#xff0c;队列中可以存储有限的、大小固定的数据项目。 任务与任务、任务与中断之间要交流的数据保存在队列中&#xff0c;叫做队列项目。 队列所能…

Python学习笔记14 -- 异常处理

try -- except 1、使用原因&#xff1a; 当用户输入不符合预期的命令时&#xff0c;尽量避免程序报错&#xff0c;并给出正常指令使用户能调整指令 try:guess_limit int(sys.argv[1]) except:guess_limit 4 # 默认为4次print("The input of chance has something wr…

代码随想录-Day36

452. 用最少数量的箭引爆气球 有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points &#xff0c;其中points[i] [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。 一支弓箭可以沿着 x 轴从不同点 完全垂…

建筑工程乙级资质审批的关键要点

企业条件&#xff1a;审批时会严格审查企业的基本情况&#xff0c;如注册资本、经营年限、法人代表及管理层的背景等&#xff0c;确保企业合法存续且信誉良好。 技术人员配置&#xff1a;这是审批的重点之一&#xff0c;需要审查技术人员的专业资格、职称、工作经验以及在岗情…

Linux--视频推流及问题

方案一&#xff1a; mjpg-streamer,它运行在ARM板上 在手机上使用浏览器直接观看视频 方案二&#xff1a; 推流端&#xff08;Fmpeg&#xff09;--rtmp-->Nginx&#xff08;流媒体服务器&#xff09;--rtmp/httpflv/hls-->浏览器、播放器 此篇文章记录方案二的具体细…

MixChecker ULTRA - 您的混音是否真正完美 ?

https://www.bilibili.com/video/BV1fn4y1Q7jo/?vd_source106698354c99ab1e247cf1ba622daa0b MixChecker ULTRA - 您的混音是否真正完美 &#xff1f; 无论您是专业的混音/母带工程师&#xff0c;还是在家中为粉丝或乐队混音音乐&#xff0c;我们都努力实现一个共同的目标&a…

Meta悄咪咪的发布多款AI新模型

大模型技术论文不断&#xff0c;每个月总会新增上千篇。本专栏精选论文重点解读&#xff0c;主题还是围绕着行业实践和工程量产。若在某个环节出现卡点&#xff0c;可以回到大模型必备腔调或者LLM背后的基础模型重新阅读。而最新科技&#xff08;Mamba,xLSTM,KAN&#xff09;则…

自定义线程池

自定义线程池需要什么 需要哪些类 MyTask /*** 自定义线程池任务* 要求每个线程有自己的编号* 线程的执行时间为0.2s*/ Data public class MyTask implements Runnable{private int id;MyTask(int id) {this.id id;}Overridepublic void run() {String name Thread.curren…