第八部分:第五节 - 生命周期与副作用 (`useEffect` Hook):组件的幕后工作

news2025/6/7 4:41:57

知识点: 组件生命周期(挂载 Mounting, 更新 Updating, 卸载 Unmounting - 高级概念),副作用 (Side Effects),useEffect Hook (用于处理副作用,如数据获取、订阅、DOM 操作),useEffect 的依赖数组,useEffect 的清理函数。

讲解:

React 组件有自己的“生命周期”,从被创建并添加到页面上(挂载),到数据或状态变化导致重新渲染(更新),再到从页面上移除(卸载)。在这些生命周期的不同阶段,我们可能需要执行一些“副作用”操作。

副作用 (Side Effects):

副作用是指在组件渲染过程中不是直接计算结果的操作。常见的副作用包括:

  • 数据获取 (Data Fetching): 从后端 API 请求数据。
  • 订阅 (Subscriptions): 建立 WebSocket 连接,监听事件等。
  • 手动修改 DOM: 直接操作浏览器 DOM (通常不推荐,除非必要)。
  • 定时器 (Timers): 设置 setTimeout 或 setInterval。
  • 日志记录 (Logging)。

这些操作不能直接放在组件函数体中(会无限循环或只执行一次),需要特殊的机制来管理。

useEffect Hook:

在功能组件中,我们使用 useEffect Hook 来处理副作用。useEffect 可以在组件渲染后执行代码。你可以把它想象成告诉 React:“在 DOM 更新后,帮我运行这段代码。”

useEffect 接收一个函数作为第一个参数,这个函数就包含了你要执行的副作用代码。

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

function DataFetcher() {
  const [data, setData] = useState(null);
  const [isLoading, setIsLoading] = useState(true);

  // 使用 useEffect 处理数据获取副作用
  useEffect(() => {
    console.log('useEffect 运行了');
    // 在这里执行异步数据获取
    fetch('https://api.example.com/data') // 假设这是一个获取数据的 API
      .then(response => response.json())
      .then(data => {
        setData(data);
        setIsLoading(false);
      })
      .catch(error => {
        console.error('数据获取出错:', error);
        setIsLoading(false);
      });

    // useEffect 的默认行为是在每次渲染后都运行副作用函数
    // 这通常不是我们想要的,需要使用依赖数组控制执行时机
  }); // 没有依赖数组,每次渲染后都运行

  if (isLoading) {
    return <p>正在加载数据...</p>;
  }

  if (!data) {
    return <p>加载数据失败。</p>;
  }

  return (
    <div>
      <h2>获取到的数据</h2>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}

useEffect 的依赖数组 (Dependency Array):

useEffect 的第二个参数是一个依赖数组。它告诉 React 副作用应该在何时重新运行。

  • 没有依赖数组: 副作用在每次渲染后都运行。
  • 空数组 []: 副作用只在组件第一次挂载时运行一次 (componentDidMount 的替代)。适合执行一次性的设置或数据获取。
  • 包含变量的数组 [variable1, variable2]: 副作用在组件第一次挂载时运行一次,并且在依赖数组中的任何变量发生变化时重新运行。适合根据某些 State 或 Props 的变化来执行副作用。
// 只在组件挂载时获取一次数据 (空数组 [])
useEffect(() => {
  console.log('组件挂载,只运行一次');
  // 获取数据的代码...
}, []); // 空依赖数组

// 当 userId 变化时重新获取数据
useEffect(() => {
  console.log('userId 或组件挂载时运行');
  if (userId) {
    // 根据新的 userId 获取用户详情
    fetch(`https://api.example.com/users/${userId}`)
      .then(response => response.json())
      .then(userData => {
        // ... 更新用户 State
      });
  }
}, [userId]); // 依赖数组包含 userId

// 没有依赖数组 (不推荐用于数据获取等异步操作,可能导致无限循环)
// useEffect(() => {
//   console.log('每次渲染后都运行');
// });

useEffect 的清理函数 (Cleanup Function):

有时候,副作用需要在组件卸载时下次副作用重新运行前进行清理,以避免内存泄漏或不必要的行为。比如清除定时器、取消订阅、关闭网络连接等。useEffect 可以选择返回一个函数,这个函数就是清理函数。

useEffect(() => {
  console.log('副作用设置');
  // 设置一个定时器
  const timerId = setInterval(() => {
    console.log('定时器运行中...');
  }, 1000);

  // 返回一个清理函数
  return () => {
    console.log('副作用清理');
    // 清除定时器
    clearInterval(timerId);
  };
}, []); // 空依赖数组,只在挂载时设置定时器,在卸载时清除

清理函数会在组件卸载时执行。如果 useEffect 因为依赖项变化而重新运行,清理函数会在新的副作用运行之前执行。

小结: useEffect Hook 是功能组件中处理副作用的核心工具。通过依赖数组可以控制副作用的执行时机(挂载时、更新时、特定依赖变化时)。返回清理函数可以处理副作用的清理工作,避免资源泄漏。理解 useEffect 是掌握在 React 中进行异步操作和与外部系统交互的关键。

练习:

  1. 在你的 my-restaurant-app 项目中,修改 MenuList 组件。
  2. 使用 useState 创建一个 State 变量 menuItemsisLoading (初始为 true)。
  3. 使用 useEffect Hook,在组件挂载时(空依赖数组),模拟从后端 API 获取菜单数据。你可以使用 setTimeout 延迟几秒来模拟网络请求。
  4. 在模拟请求成功后,更新 menuItems State,并将 isLoading 设置为 false。
  5. 在组件的 JSX 中,使用条件渲染:如果 isLoading 为 true,显示“菜单加载中…”,否则渲染菜单列表 (menuItems.map(...))。
  6. (进阶)创建一个新的组件 Timer.jsx。使用 useStateuseEffect 来创建一个简单的计时器,每秒更新并显示当前时间。在 useEffect 中设置 setInterval,并返回一个清理函数来清除定时器。

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

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

相关文章

DeepSwiftSeek 开源软件 |用于 DeepSeek LLM 模型的 Swift 客户端 |轻量级和高效的 DeepSeek 核心功能通信

​一、软件介绍 文末提供程序和源码下载 DeepSeek Swift SDK 是一个轻量级且高效的基于 Swift 的客户端&#xff0c;用于与 DeepSeek API 进行交互。它支持聊天消息完成、流式处理、错误处理以及使用高级参数配置 DeepSeekLLM。 二、Features 特征 Supports chat completion …

Flask-Login使用示例

项目结构 首先创建以下文件结构&#xff1a; flask_login_use/ ├── app.py ├── models.py ├── requirements.txt └── templates/├── base.html├── index.html├── login.html├── register.html└── profile.html1. requirements.txt Flask2.3.3 Fl…

web第九次课后作业--SpringBoot基于mybatis实现对数据库的操作

前言 在前面我们学习MySQL数据库时&#xff0c;都是利用图形化客户端工具(如&#xff1a;idea、datagrip)&#xff0c;来操作数据库的。 在客户端工具中&#xff0c;编写增删改查的SQL语句&#xff0c;发给MySQL数据库管理系统&#xff0c;由数据库管理系统执行SQL语句并返回执…

wordpress免费主题网站

这是一款WordPress主题&#xff0c;由jianzhanpress开发&#xff0c;可以免费下载。专为中小微企业设计&#xff0c;提供专业的网站建设、网站运营维护、网站托管和网站优化等服务。主题设计简约、现代&#xff0c;适合多种行业需求。 主要特点&#xff1a; 多样化展示&#…

Go中的协程并发和并发panic处理

1 协程基础 1.1 协程定义&#xff08;Goroutine&#xff09; 概念&#xff1a;Go 语言特有的轻量级线程&#xff0c;由 Go 运行时&#xff08;runtime&#xff09;管理&#xff0c;相比系统线程&#xff08;Thread&#xff09;&#xff0c;创建和销毁成本极低&#xff0c;占用…

Qt Creator工具编译器配置

1、打开Qt Creator&#xff0c;工具-->选项 2、选择"编译器"&#xff0c;Manual配置编译器。 初始化填入“C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\cl.exe”&#xff0c;选择64位amd64。 ABI根据msvc版本进行选择msvc2015. 3、新建项目…

Spring框架学习day7--SpringWeb学习(概念与搭建配置)

SpringWeb1.SpringWeb特点2.SpringWeb运行流程3.SpringWeb组件4.搭建项目结构图&#xff1a;4.1导入jar包4.2在Web.xml配置**4.2.1配置统一拦截分发器 DispatcherServlet**4.2.2开启SpringWeb注解&#xff08;spring.xml&#xff09; 5.处理类的搭建6.SpringWeb请求流程(自己理…

打造高效多模态RAG系统:原理与评测方法详解

引言 随着信息检索与生成式AI的深度融合&#xff0c;检索增强生成&#xff08;RAG, Retrieval-Augmented Generation&#xff09; 已成为AI领域的重要技术方向。传统RAG系统主要依赖文本数据&#xff0c;但真实世界中的信息往往包含图像、表格等多模态内容。多模态RAG&#xf…

【C#】Quartz.NET怎么动态调用方法,并且根据指定时间周期执行,动态配置类何方法以及Cron表达式,有请DeepSeek

&#x1f339;欢迎来到《小5讲堂》&#x1f339; &#x1f339;这是《C#》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。&#x1f339; &#x1f339;温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01;&#…

02 Deep learning神经网络的编程基础 逻辑回归--吴恩达

逻辑回归 逻辑回归是一种用于解决二分类任务&#xff08;如预测是否是猫咪等&#xff09;的统计学习方法。尽管名称中包含“回归”&#xff0c;但其本质是通过线性回归的变体输出概率值&#xff0c;并使用Sigmoid函数将线性结果映射到[0,1]区间。 以猫咪预测为例 假设单个样…

MySQL的并发事务问题及事务隔离级别

一、并发事务问题 1). 赃读&#xff1a;一个事务读到另外一个事务还没有提交的数据。 比如 B 读取到了 A 未提交的数据。 2). 不可重复读&#xff1a;一个事务先后读取同一条记录&#xff0c;但两次读取的数据不同&#xff0c;称之为不可重复读。 事务 A 两次读取同一条记录&…

ProfiNet 分布式 IO 在某污水处理厂的应用

随着城市化进程的加速&#xff0c;污水处理厂的规模和复杂性不断增加&#xff0c;对自动化控制系统的要求也越来越高。PROfinet 分布式 IO 作为一种先进的工业通信技术&#xff0c;以其高速、可靠、灵活的特性&#xff0c;为污水处理厂的自动化升级提供了有力支持。本文将结合某…

vue2 , el-select 多选树结构,可重名

人家antd都支持&#xff0c;elementplus 也支持&#xff0c;vue2的没有&#xff0c;很烦。 网上其实可以搜到各种的&#xff0c;不过大部分不支持重名&#xff0c;在删除的时候可能会删错&#xff0c;比如树结构1F的1楼啊&#xff0c;2F的1楼啊这种同时勾选的情况。。 可以全…

Excel处理控件Aspose.Cells教程:使用 C# 从 Excel 进行邮件合并

邮件合并功能让您能够轻松批量创建个性化文档&#xff0c;例如信函、电子邮件、发票或证书。您可以从模板入手&#xff0c;并使用电子表格中的数据进行填充。Excel 文件中的每一行都会生成一个新文档&#xff0c;并在正确的位置包含正确的详细信息。这是一种自动化重复性任务&a…

EXCEL通过DAX Studio获取端口号连接PowerBI

EXCEL通过DAX Studio获取端口号连接PowerBI 昨天我分享了EXCEL链接模板是通过获取端口号和数据库来连接PowerBI模型的&#xff0c;链接&#xff1a;浅析EXCEL自动连接PowerBI的模板&#xff0c;而DAX Studio可以获取处于打开状态的PowerBI的端口号。 以一个案例分享如何EXCEL…

C# 委托UI控件更新例子,何时需要使用委托

1. 例子1 private void UdpRxCallBackFunc(UdpDataStruct info) {// 1. 前置检查防止无效调用if (textBoxOutput2.IsDisposed || !textBoxOutput2.IsHandleCreated)return;// 2. 使用正确的委托类型Invoke(new Action(() >{// 3. 双重检查确保安全if (textBoxOutput2.IsDis…

大模型数据流处理实战:Vue+NDJSON的Markdown安全渲染架构

在Vue中使用HTTP流接收大模型NDJSON数据并安全渲染 在构建现代Web应用时&#xff0c;处理大模型返回的流式数据并安全地渲染到页面是一个常见需求。本文将介绍如何在Vue应用中通过普通HTTP流接收NDJSON格式的大模型响应&#xff0c;使用marked、highlight.js和DOMPurify等库进…

python项目如何创建docker环境

这里写自定义目录标题 python项目创建docker环境docker配置国内镜像源构建一个Docker 镜像验证镜像合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPant…

PyTorch--池化层(4)

池化层&#xff08;Pooling Layer&#xff09; 用于降低特征图的空间维度&#xff0c;减少计算量和参数数量&#xff0c;同时保留最重要的特征信息。 池化作用&#xff1a;比如1080p视频——720p 池化层的步长默认是卷积核的大小 ceil 允许有出界部分&#xff1b;floor 不允许…

2025年大模型平台落地实践研究报告|附75页PDF文件下载

本报告旨在为各行业企业在建设落地大模型平台的过程中&#xff0c;提供有效的参考和指引&#xff0c;助力大模型更高效更有价值地规模化落地。本报告系统性梳理了大模型平台的发展背景、历程和现状&#xff0c;结合大模型平台的特点提出了具体的落地策略与路径&#xff0c;同时…