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

【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 的值,并触发组件重新渲染。

工作机制:
  1. 首次渲染:当组件第一次渲染时,React 会初始化状态并将初始值(如 0)存储在内部的状态列表中。
  2. 后续渲染:每次组件重新渲染时,React 不会重新初始化状态,而是从其内部存储中取出最新的状态值,并将其传递给组件函数中的 useState
  3. 状态更新:当 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 为每个组件实例维护了一个“状态钩子”链表,组件每次渲染时,它依次从这个链表中获取对应的状态值。

流程概述:
  1. 状态存储:每个组件的状态被存储在 React 内部的某个数据结构中,通常是一个状态列表。
  2. 状态链表:每个调用 useState 的组件,都有一个状态链表,其中存储了状态值和 setState 函数。
  3. 状态更新:当调用 setState 时,React 会更新链表中的状态值,然后调度一次渲染。
  4. 下一次渲染时:在下一次渲染时,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 中&#xff0c;setState 通过 React 内部的状态管理机制来记住上一个状态值。即使每次组件重新渲染时&#xff0c;函数组件会被重新执行&#xff0c;React 仍能通过其内部的状态管理系统保持和追踪组件的状态变化。下面详细解释其工作原理&#xff1a; 1. setState 的…...

Vue3 使用CryptoJS加密

为什么要加密&#xff1f; 现在的互联网世界充满了各种各样的信息&#xff0c;有些信息非常重要&#xff0c;比如密码、个人信息等。如果我们把这些信息直接发送到服务器&#xff0c;别人可能会截取到&#xff0c;然后偷走我们的信息。为了避免这种情况发生&#xff0c;我们需…...

Feign的使用

一、Feign 介绍 Feign 是一个声明式的 HTTP 客户端&#xff0c;它使得编写 HTTP 客户端变得更加简单。在微服务架构中&#xff0c;使用 Feign 可以轻松地调用其他服务。Feign 内置了 Ribbon 实现负载均衡。 二、Feign 的使用步骤 引入依赖&#xff1a; 在项目的 pom.xml 文件…...

前端反接保护:实用方案解析与探讨

前端反接保护通常采用肖特基二极管方案或PMOS/NMOS方案&#xff0c;本文另外介绍一种理想二极管方案。 1、肖特基二极管方案 由于肖特基二极管具有正向导通电压&#xff0c;只能用于小电流场合&#xff0c;甚至于直接使用普通的整流二极管。比如1A电流&#xff0c;设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】方法 和 递归 的应用

&#x1f525;博客主页&#x1f525;&#xff1a;【 坊钰_CSDN博客 】 欢迎各位点赞&#x1f44d;评论✍收藏⭐ 目录 1. 方法的含义 1.1 例子 1.2 方法的概念 2. 方法的定义 3. 实参和形参 3.1 实参和形参的关系 4. 方法的重载 5. 递归 5.1 递归练习 6. 小结 1. 方法的…...

JVS低代码轻应用是什么?是如何拼装的?这篇文章讲的非常详细

1.1JVS轻应用是什么&#xff1f; 轻应用与传统应用的开发过程区别 传统开发&#xff08;原生开发&#xff09;采用的方式&#xff1a;①需求了解 ②产品原型③UI设计④建库建表⑤前端还原⑥后端开发⑦前后端联调⑧功能测试⑨部署上线轻应用开发方式&#xff08;配置化拼装&…...

K210(openMV)与STM32 通信教程

目录 前言&#xff1a; 一、K210 串口部分教程 二、STM32部分 前言&#xff1a; 很多打比赛的同学&#xff0c;通常只是用K210 或者openMV来进行视觉部分的信息采集&#xff0c;传输数据给STM32&#xff08;或者其他主控那边&#xff09;进行对分析&#xff0c;对小车或者舵…...

【HarmonyOS】HMRouter使用详解(三)生命周期

生命周期&#xff08;Lifecycle&#xff09; 使用HMRouter的页面跳转时&#xff0c;想实现和Navigation一样的生命周期时&#xff0c;需要通过新建生命周期类来实现对页面对某一个生命周期的监控。 新建Lifecycle类 通过继承IHMLifecycle接口实现生命周期接口的方法重写。 通过…...

Docker 教程三 (Ubuntu Docker安装)

Ubuntu Docker 安装 Docker Engine-Community 支持以下的 Ubuntu 版本&#xff1a; Xenial 16.04 (LTS)Bionic 18.04 (LTS)Cosmic 18.10Disco 19.04 其他更新的版本…… Docker Engine - Community 支持上 x86_64&#xff08;或 amd64&#xff09;armhf&#xff0c;arm64&am…...

Redis:持久化

Redis&#xff1a;持久化 持久化RDBdump.rdb优缺点 AOF文件同步重写机制 混合持久化 持久化 虽然Redis是一个内存级别的数据库&#xff0c;但是Redis也是有持久化的能力的。当系统崩溃时&#xff0c;Redis就会被强制退出&#xff0c;此时内存中的数据就会丢失。为了能够在下次…...

精准监控,高效运营 —— 商品信息实时分析为商家带来新机遇

在现代商业环境中&#xff0c;精准监控和高效运营是商家成功的关键。通过实时分析商品信息&#xff0c;商家可以洞察市场趋势、优化库存管理、提升销售策略&#xff0c;从而抓住新的商业机遇。本文将介绍如何利用Python和一些流行的数据分析工具来实现商品信息的实时分析&#…...

Nginx应用配置实战

Nginx通用部署 Nginx常见参数介绍 Nginx 配置文件中的指令和参数决定了它的行为。下面详细介绍一些常见的 Nginx 参数&#xff0c;以帮助你更好地理解和配置 Nginx。 1. worker_processes worker_processes auto;作用&#xff1a;设置 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]的元素组合个数 转换而来&#xff0c;其中j为nums所有元素的下标 而总和target - nums[j]的元素组合个数 可以由 总和为target - nums[j] - nums[k]的…...

Midjourney中文版:创意无限,艺术之旅由此启程

Midjourney中文版——一个将你的文字想象转化为视觉艺术的神奇平台。无需繁琐的绘画技巧&#xff0c;只需简单的文字描述&#xff0c;你就能开启一场前所未有的艺术之旅。 Midjourney AI超强绘画 (原生态系统&#xff09;用户端&#xff1a;Ai Loadinghttps://www.mjdiscord.c…...

安装R和RStudio:开始你的数据分析之旅

数据分析是当今世界中一个非常热门的领域&#xff0c;而R语言是进行数据分析的强大工具之一。R是一种编程语言和软件环境&#xff0c;用于统计计算和图形表示。RStudio是一个集成开发环境&#xff08;IDE&#xff09;&#xff0c;它为R语言提供了一个更加友好和高效的工作环境。…...

如何使用python连接数据库?

数据分析离不开数据库&#xff0c;如何使用python连接数据库呢&#xff1f;听我娓娓道来哈 该笔记参考了PyMySQL官方文档和《python数据采集》关于数据存储的部分&#xff0c;欢迎大家去阅读原著&#xff0c;相信会理解的更加透彻。 补充&#xff1a;文末增加Oracle数据库的连…...

停车位识别数据集 图片数量12416张YOLO,xml和txt标签都有; 2类类别:space-empty,space-occupied;

YOLO停车位识别 图片数量12416张&#xff0c;xml和txt标签都有&#xff1b; 2类类别&#xff1a;space-empty&#xff0c;space-occupied&#xff1b; 用于yolo&#xff0c;Python&#xff0c;目标检测&#xff0c;机器学习&#xff0c;人工智能&#xff0c;深度学习&#xff0…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...