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

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

知识点: 组件生命周期(挂载 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.lryc.cn/news/2402471.html

相关文章:

  • docker 搭建php 开发环境 添加扩展redis、swoole、xdebug(2)
  • DeepSwiftSeek 开源软件 |用于 DeepSeek LLM 模型的 Swift 客户端 |轻量级和高效的 DeepSeek 核心功能通信
  • Flask-Login使用示例
  • React Hooks 基础指南
  • web第九次课后作业--SpringBoot基于mybatis实现对数据库的操作
  • 沪铜6月想法
  • 网络通信核心概念全解析:从IP地址到TCP/UDP实战
  • Spring 中的disposableBean介绍
  • 【Linux命令学习】获取cpu信息 - lscpu命令学习
  • wordpress免费主题网站
  • Go中的协程并发和并发panic处理
  • Qt Creator工具编译器配置
  • 从零开始的数据结构教程(六) 贪心算法
  • Spring框架学习day7--SpringWeb学习(概念与搭建配置)
  • 打造高效多模态RAG系统:原理与评测方法详解
  • SSM 框架核心知识详解(Spring + SpringMVC + MyBatis)
  • 1.2 fetch详解
  • 【C#】Quartz.NET怎么动态调用方法,并且根据指定时间周期执行,动态配置类何方法以及Cron表达式,有请DeepSeek
  • 02 Deep learning神经网络的编程基础 逻辑回归--吴恩达
  • Android Native 内存泄漏检测全解析:从原理到工具的深度实践
  • React---扩展补充
  • HTML 中 class 属性介绍、用法
  • MySQL的并发事务问题及事务隔离级别
  • ProfiNet 分布式 IO 在某污水处理厂的应用
  • vue2使用笔记、vue2和vue3的区别
  • Vue2数组数字字段求和技巧 数字求和方法
  • vue2 , el-select 多选树结构,可重名
  • Excel处理控件Aspose.Cells教程:使用 C# 从 Excel 进行邮件合并
  • Jenkins | Jenkins构建成功服务进程关闭问题
  • 模块化架构下的前端调试体系建设:WebDebugX 与多工具协同的工程实践