【React】setState (useState) 是怎么记住上一个状态值的?
在 React 中,setState 通过 React 内部的状态管理机制来记住上一个状态值。即使每次组件重新渲染时,函数组件会被重新执行,React 仍能通过其内部的状态管理系统保持和追踪组件的状态变化。下面详细解释其工作原理:
1. setState 的工作原理
setState 是 React 的核心状态更新方法,用于更新组件的状态,并且触发重新渲染。React 中,组件的状态存储在组件实例中(类组件)或通过 React 的 Hook 系统(函数组件)进行管理。在调用 setState 时,React 并不会立即更新状态,而是将更新请求放入一个队列中,并批量处理这些更新,以提高性能。
在函数组件中,useState 是一个用于管理状态的 Hook。每次调用 setState 时,React 将使用更新队列,并在合适的时机将最新的状态重新传递给组件,确保每次渲染时都能够记住最新的状态。
2. 函数组件的状态记忆(useState)
函数组件本质上是无状态的,函数内部的局部变量在每次渲染后都会被销毁。然而,React 通过 useState Hook 来保持状态的持久化,它会将状态与组件进行关联,即使组件重新渲染,React 仍然能够保持状态。
function MyComponent() {const [count, setCount] = useState(0); // 初始化状态为 0return (<button onClick={() => setCount(count + 1)}>{count}</button>);
}
在这个例子中,useState(0) 初始化了 count 为 0,setCount 是用于更新 count 值的函数。每次点击按钮时,setCount 会更新 count 的值,并触发组件重新渲染。
工作机制:
- 首次渲染:当组件第一次渲染时,React 会初始化状态并将初始值(如
0)存储在内部的状态列表中。 - 后续渲染:每次组件重新渲染时,React 不会重新初始化状态,而是从其内部存储中取出最新的状态值,并将其传递给组件函数中的
useState。 - 状态更新:当
setState(如setCount)被调用时,React 将更新的状态值存入其内部的状态存储,并在下一次渲染时使用该值。通过这种方式,React 能够记住并管理状态值。
function App() {const [index, setIndex] = useState(0)// const handleClick = () => {setIndex(index + 1)setIndex(index + 1)setIndex(index + 1)console.log('index改变', index);}return (<div className="App">{/*经过一次点击后 index 为 1,而不是3 ,是因为 setState 队列中如果有相同的 setState 会自动忽略后续的 set 相当于自带防抖*/}{/*需要需要保留上一次 set 的值,需要传入一个回调 参数用来接收上一次的值,队列完成更新后再调用 render 渲染组件*/}<div>{index}</div><button onClick={handleClick}>index + 1</button></div>);
}
如果 setState 不相同呢?
const handleClick = () => {setIndex(index + 1)setIndex(index + 2)setIndex(index + 3)console.log('index改变', index);
}
此时页面展示为 3,因为 set state 不同,后续会正常执行异步操作。
3. React 如何记住状态(闭包和 Hook 内部机制)
React 通过闭包和 Hooks 系统来管理状态,确保在多次渲染之间保持状态的一致性。useState 背后的工作方式是,React 为每个组件实例维护了一个“状态钩子”链表,组件每次渲染时,它依次从这个链表中获取对应的状态值。
流程概述:
- 状态存储:每个组件的状态被存储在 React 内部的某个数据结构中,通常是一个状态列表。
- 状态链表:每个调用
useState的组件,都有一个状态链表,其中存储了状态值和setState函数。 - 状态更新:当调用
setState时,React 会更新链表中的状态值,然后调度一次渲染。 - 下一次渲染时:在下一次渲染时,React 从该链表中获取最新的状态值,确保状态是连续且正确的。
使用 setState 更新状态:
const [count, setCount] = useState(0);function handleClick() {setCount(prevCount => prevCount + 1);
}
这里 setCount 可以接收一个函数,该函数的参数 prevCount 是 React 自动传入的上一次的状态值。即使多个 setState 在同一渲染周期中执行,React 也会确保传递的状态值是最新的。
4. React 的批量更新机制
React 在同一个事件或生命周期方法中会对多个状态更新进行批量处理。即使多次调用 setState,React 也不会立即更新状态,而是等到事件处理完后再进行批量更新,并触发一次渲染。
const [count, setCount] = useState(0);function handleClick() {setCount(count + 1);setCount(count + 1);
}
在这种情况下,虽然两次调用 setCount,React 会批量更新,并只会触发一次渲染,最终 count 只会增加一次。
总结
- 状态持久化:React 通过
useState和内部状态存储系统来管理状态,每次渲染时,React 会从状态链表中获取最新状态,并保持状态的连续性。 - 闭包与 Hooks:React 的 Hooks 系统和闭包机制确保状态不会在多次渲染中丢失,
setState会更新状态链表,并在下一次渲染时应用最新状态。 - 批量处理:React 对
setState调用进行了优化,多个setState会被批量处理,从而避免不必要的多次渲染。
相关文章:
【React】setState (useState) 是怎么记住上一个状态值的?
在 React 中,setState 通过 React 内部的状态管理机制来记住上一个状态值。即使每次组件重新渲染时,函数组件会被重新执行,React 仍能通过其内部的状态管理系统保持和追踪组件的状态变化。下面详细解释其工作原理: 1. setState 的…...
Vue3 使用CryptoJS加密
为什么要加密? 现在的互联网世界充满了各种各样的信息,有些信息非常重要,比如密码、个人信息等。如果我们把这些信息直接发送到服务器,别人可能会截取到,然后偷走我们的信息。为了避免这种情况发生,我们需…...
Feign的使用
一、Feign 介绍 Feign 是一个声明式的 HTTP 客户端,它使得编写 HTTP 客户端变得更加简单。在微服务架构中,使用 Feign 可以轻松地调用其他服务。Feign 内置了 Ribbon 实现负载均衡。 二、Feign 的使用步骤 引入依赖: 在项目的 pom.xml 文件…...
前端反接保护:实用方案解析与探讨
前端反接保护通常采用肖特基二极管方案或PMOS/NMOS方案,本文另外介绍一种理想二极管方案。 1、肖特基二极管方案 由于肖特基二极管具有正向导通电压,只能用于小电流场合,甚至于直接使用普通的整流二极管。比如1A电流,设D1的正向…...
【C++】第五节:内存管理
1、C/C内存分布 看下面一段代码 int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] { 1, 2, 3, 4 };char char2[] "abcd";const char* pChar3 "abcd";int* ptr1 (int*)malloc(s…...
【Java SE】方法 和 递归 的应用
🔥博客主页🔥:【 坊钰_CSDN博客 】 欢迎各位点赞👍评论✍收藏⭐ 目录 1. 方法的含义 1.1 例子 1.2 方法的概念 2. 方法的定义 3. 实参和形参 3.1 实参和形参的关系 4. 方法的重载 5. 递归 5.1 递归练习 6. 小结 1. 方法的…...
JVS低代码轻应用是什么?是如何拼装的?这篇文章讲的非常详细
1.1JVS轻应用是什么? 轻应用与传统应用的开发过程区别 传统开发(原生开发)采用的方式:①需求了解 ②产品原型③UI设计④建库建表⑤前端还原⑥后端开发⑦前后端联调⑧功能测试⑨部署上线轻应用开发方式(配置化拼装&…...
K210(openMV)与STM32 通信教程
目录 前言: 一、K210 串口部分教程 二、STM32部分 前言: 很多打比赛的同学,通常只是用K210 或者openMV来进行视觉部分的信息采集,传输数据给STM32(或者其他主控那边)进行对分析,对小车或者舵…...
【HarmonyOS】HMRouter使用详解(三)生命周期
生命周期(Lifecycle) 使用HMRouter的页面跳转时,想实现和Navigation一样的生命周期时,需要通过新建生命周期类来实现对页面对某一个生命周期的监控。 新建Lifecycle类 通过继承IHMLifecycle接口实现生命周期接口的方法重写。 通过…...
Docker 教程三 (Ubuntu Docker安装)
Ubuntu Docker 安装 Docker Engine-Community 支持以下的 Ubuntu 版本: Xenial 16.04 (LTS)Bionic 18.04 (LTS)Cosmic 18.10Disco 19.04 其他更新的版本…… Docker Engine - Community 支持上 x86_64(或 amd64)armhf,arm64&am…...
Redis:持久化
Redis:持久化 持久化RDBdump.rdb优缺点 AOF文件同步重写机制 混合持久化 持久化 虽然Redis是一个内存级别的数据库,但是Redis也是有持久化的能力的。当系统崩溃时,Redis就会被强制退出,此时内存中的数据就会丢失。为了能够在下次…...
精准监控,高效运营 —— 商品信息实时分析为商家带来新机遇
在现代商业环境中,精准监控和高效运营是商家成功的关键。通过实时分析商品信息,商家可以洞察市场趋势、优化库存管理、提升销售策略,从而抓住新的商业机遇。本文将介绍如何利用Python和一些流行的数据分析工具来实现商品信息的实时分析&#…...
Nginx应用配置实战
Nginx通用部署 Nginx常见参数介绍 Nginx 配置文件中的指令和参数决定了它的行为。下面详细介绍一些常见的 Nginx 参数,以帮助你更好地理解和配置 Nginx。 1. worker_processes worker_processes auto;作用:设置 Nginx 处理请求的工作进程数量。auto …...
html实现倒计时
参考网址 <!DOCTYPE html> <html> <head><title>倒计时示例</title> </head> <body><h1 id"titleCountDown"></h1><div id"countdown"></div><script>// 目标日期var targetDat…...
HTMLCSS练习
1) 效果如下 2) 代码如下 2.1) HTML <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" conte…...
LeetCode讲解篇之377. 组合总和 Ⅳ
文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 总和为target的元素组合个数 可以由 总和为target - nums[j]的元素组合个数 转换而来,其中j为nums所有元素的下标 而总和target - nums[j]的元素组合个数 可以由 总和为target - nums[j] - nums[k]的…...
Midjourney中文版:创意无限,艺术之旅由此启程
Midjourney中文版——一个将你的文字想象转化为视觉艺术的神奇平台。无需繁琐的绘画技巧,只需简单的文字描述,你就能开启一场前所未有的艺术之旅。 Midjourney AI超强绘画 (原生态系统)用户端:Ai Loadinghttps://www.mjdiscord.c…...
安装R和RStudio:开始你的数据分析之旅
数据分析是当今世界中一个非常热门的领域,而R语言是进行数据分析的强大工具之一。R是一种编程语言和软件环境,用于统计计算和图形表示。RStudio是一个集成开发环境(IDE),它为R语言提供了一个更加友好和高效的工作环境。…...
如何使用python连接数据库?
数据分析离不开数据库,如何使用python连接数据库呢?听我娓娓道来哈 该笔记参考了PyMySQL官方文档和《python数据采集》关于数据存储的部分,欢迎大家去阅读原著,相信会理解的更加透彻。 补充:文末增加Oracle数据库的连…...
停车位识别数据集 图片数量12416张YOLO,xml和txt标签都有; 2类类别:space-empty,space-occupied;
YOLO停车位识别 图片数量12416张,xml和txt标签都有; 2类类别:space-empty,space-occupied; 用于yolo,Python,目标检测,机器学习,人工智能,深度学习࿰…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
