state的异步跟新

embedded/2025/1/23 16:13:56/

预测下刷新页面后,页面上会有啥数字出现

import React, { useState, useEffect } from "react";const Bpp = () => {const [data, setData] = useState([]);// const [loading, setLoading] = useState(true);const [errorData, setErrorData] = useState([]);useEffect(() => {const newList = [];for (let i = 0; i < 1000; i++) {newList.push({name: `标题${i}`,});}setData(newList);setErrorData(data);}, []);return (<div>{data.length},{errorData.length}</div>)
}export default Bpp;

一、组件的初始化阶段

  1. 状态初始化

    • const [data, setData] = useState([]);:将 data 初始化为一个空数组。
    • const [errorData, setErrorData] = useState([]);:将 errorData 初始化为一个空数组。
  2. 首次渲染

    • 当组件首次渲染时,会执行 return 语句,显示 <div>{data.length},{errorData.length}</div>
    • 由于 data 和 errorData 都是初始状态,它们的长度都是 0,所以页面会显示 0,0

二、useEffect 的执行

  1. useEffect 触发

    • 由于 useEffect 的依赖项数组为 [],该 useEffect 只会在组件挂载后执行一次,类似于 componentDidMount 生命周期方法。
    • 当组件挂载完成后,useEffect 开始执行。
  2. useEffect 内部操作

    • 一个包含 1000 个元素的 newList 被创建:
      const newList = [];
      for (let i = 0; i < 1000; i++) {newList.push({name: `标题${i}`,});
      }
      
    • setData(newList); 被调用:
      • 这将触发 React 状态更新,把 data 状态更新为包含 1000 个元素的数组。但 React 的状态更新是异步的,意味着 data 的更新不会立即完成。React 不会立即更新 data 的值,而是会将状态更新排入队列,并在稍后进行更新
    • setErrorData(data); 被调用:
      • 由于状态更新的异步性,此时 data 仍然保持其旧值(即空数组),因为 setData 操作尚未完成更新。因此,setErrorData 会将 errorData 状态更新为一个空数组。

三、最终结果

  1. 后续渲染
    • 在 useEffect 执行之后,组件会重新渲染。
    • 此时,data 状态已经更新,因为 setData 的更新操作已经完成,所以 data.length 为 1000
    • 但是,errorData 状态仍然是空数组,因为在 useEffect 中,setErrorData 接收到的是 data 的旧值,所以 errorData.length 为 0

  • 页面上最终显示 1000,0 的原因是 useEffect 内部状态更新的顺序和异步特性。在 useEffect 中调用 setData(newList) 不会立即更新 data,而后续的 setErrorData(data) 使用的是 data 的旧值(即初始的空数组),导致 errorData 最终仍然是一个空数组,而 data 最终更新为包含 1000 个元素的数组。

解决代码

import React, { useState, useEffect } from "react";const Bpp = () => {const [data, setData] = useState([]);// const [loading, setLoading] = useState(true);const [errorData, setErrorData] = useState([]);useEffect(() => {const newList = [];for (let i = 0; i < 1000; i++) {newList.push({name: `标题${i}`,});}setData(newList);}, []);useEffect(() => {setErrorData(data);}, [data]);return (<div>{data.length},{errorData.length}</div>)
}export default Bpp;


http://www.ppmy.cn/embedded/156340.html

相关文章

窗口栏组件

在Qt中&#xff0c;窗口的布局可以由多个常用的部件组成。你提供的代码涉及了菜单栏、工具栏、状态栏、中心部件和铆接部件&#xff08;即停靠窗口&#xff09;。下面是每个部件的详细解析&#xff1a; 1. 菜单栏 (QMenuBar) Qt中的菜单栏用来创建应用程序的顶部菜单&#xf…

新能源监控平台都管理哪些数据

北理新源信息科技有限公司&#xff08;简称“北理新源”&#xff09;依托北京理工大学电动车辆国家工程研究中心&#xff0c;建设和运营了“新能源汽车国家监测与管理平台”。该平台是国家级的新能源汽车数据监管平台&#xff0c;主要负责对新能源汽车的运行数据进行采集、监测…

小米Vela操作系统开源:AIoT时代的全新引擎

小米近日正式开源了其物联网嵌入式软件平台——Vela操作系统&#xff0c;并将其命名为OpenVela。这一举动在AIoT&#xff08;人工智能物联网&#xff09;领域掀起了不小的波澜&#xff0c;也为开发者们提供了一个强大的AI代码生成器和开发平台。OpenVela项目源代码已托管至GitH…

Java设计模式 六 原型模式 (Prototype Pattern)

原型模式 (Prototype Pattern) 原型模式是一种创建型设计模式&#xff0c;通过复制现有对象来创建新对象&#xff0c;而不是直接实例化类。这种模式适用于创建成本较高的对象&#xff0c;或者需要重复创建相似对象的场景。 原型模式的核心思想是&#xff1a; 通过对象自身提供…

使用Redis防止重复发送RabbitMQ消息

问题 今天遇到一个问题&#xff0c;发送MQ消息的时候需要保证不会重复发送&#xff0c;注意不是可靠到达&#xff08;可靠到达可以通过消息确认机制和回调接口保证&#xff09;&#xff0c;这里保证的是不会生产多条一样的消息。 方法 综合讨论下来决定使用Redis缓存来解决&…

Docker 国内镜像源

目录 概述 步骤 参考资料 概述 自 2024-06-06 开始&#xff0c;阿里&#xff0c;腾讯、中科大等国内的 Docker Hub 镜像加速器相继停止服务&#xff0c;总结了网友整理出来一些其他国内 Docker Hub 镜像源&#xff0c;经过测试可以使用。 步骤 配置 Docker 守护程序 修改…

Kubectl常用命令操作

kubectl 命令格式&#xff1a; kubectl command type name command:表示子命令&#xff0c;用于操作kubernetes的集群资源对象&#xff0c;如&#xff1a;create delete describe get apply type:资源对象的类型 name:资源对象的名称 1.创建资源对象 kubectl create -f my…

Blazor-Blazor WebAssmbly项目结构(上)

创建项目 今天我们来创建一个BlazorWebAssmbly项目&#xff0c;来看看项目结构是如何得&#xff0c;我们创建带模板得项目&#xff0c;会创建出一个demo&#xff0c;来看看项目结构。 创建的项目可以直接启动运行&#xff0c;首次启动会看见加载的过程&#xff0c;这个过程…