深入解析 React 的 useEffect:从入门到实战

文章目录

  • 前言
    • 一、为什么需要 `useEffect`?
      • 核心作用:
    • 二、`useEffect` 的基础用法
      • 1. 基本语法
      • 2. 依赖项数组的作用
    • 三、依赖项数组演示
      • 1. 空数组 `[]`:
      • 2.无依赖项(空)
      • 3.有依赖项
    • 四、清理副作用函数
      • 实战案例演示
      • 1. 清除定时器
      • 2. 取消网络请求
  • 总结


前言

在 React 函数组件中,useEffect 是处理副作用(Side Effects)的核心 Hook。无论是数据获取、订阅事件、手动操作 DOM,还是其他异步任务,useEffect 都能帮助开发者优雅地管理这些副作用。然而,它的使用场景复杂且容易踩坑。本文将带你从基础到实战,全面掌握 useEffect 的核心原理和最佳实践。


一、为什么需要 useEffect

在类组件中,副作用通常通过生命周期方法(如 componentDidMountcomponentDidUpdatecomponentWillUnmount)管理。但在函数组件中,由于没有生命周期方法,React 提供了 useEffect 来统一处理这些场景。

核心作用:

  1. 数据获取:在组件挂载后从 API 获取数据。
  2. 订阅/取消订阅:如 WebSocket、事件监听等。
  3. 手动操作 DOM:如调整滚动位置、聚焦输入框。
  4. 清理副作用:避免内存泄漏或重复操作。

二、useEffect 的基础用法

1. 基本语法

	import { useEffect } from 'react';function MyComponent() {useEffect(() => {// 副作用代码return () => {// 清理函数(可选)};}, [dependencies]); // 依赖项数组(可选) return <div>...</div>;}

2. 依赖项数组的作用

  • 空数组:只在组件挂载时执行一次(类似 componentDidMount)。
  • 无依赖项:每次组件渲染后都会执行(类似 componentDidUpdate,但容易引发性能问题)。
  • 有依赖项:当依赖项变化时重新执行。

三、依赖项数组演示

1. 空数组 []

只在组件挂载时执行一次(类似 componentDidMount)**

场景:组件挂载时执行一次初始化操作(如获取初始数据、订阅事件)。

	import { useState, useEffect } from 'react';function InitialDataLoader() {const [data, setData] = useState(null);useEffect(() => {async function fetchInitialData() {const response = await fetch('/api/initial-data');const result = await response.json();setData(result);}fetchInitialData();}, []); // 空数组:仅在组件挂载时执行if (!data) return <div>Loading initial data...</div>;return <div>{JSON.stringify(data)}</div>;}
  • useEffect 仅在组件挂载时执行一次,适合初始化操作。
  • 清理函数(可选)通常用于取消订阅或清除资源(如 AbortController)。

2.无依赖项(空)

无依赖项:每次组件渲染后都会执行(类似 componentDidUpdate,但容易引发性能问题

场景:每次组件渲染后都执行某些操作(如记录日志、强制更新)。
注意:无依赖项的 useEffect 通常不推荐使用,除非明确需要每次渲染后执行。

	import { useEffect } from 'react';function LoggerComponent() {useEffect(() => {console.log('Component rendered or updated');}); // 无依赖项:每次渲染后都会执行return <div>Check the console for render logs.</div>;}
  • 每次组件渲染(包括状态更新、父组件更新等)后都会触发 useEffect
  • 慎用:可能导致性能问题(如无限循环、频繁 API 调用)。

3.有依赖项

:当依赖项变化时重新执行

场景:依赖项(如状态、props)变化时重新执行副作用(如数据更新、重新订阅)。

	import { useState, useEffect } from 'react';function UserData({ userId }) {const [user, setUser] = useState(null);useEffect(() => {async function fetchUser() {const response = await fetch(`/api/users/${userId}`);const data = await response.json();setUser(data);}fetchUser();}, [userId]); // 依赖项:userId 变化时重新执行 if (!user) return <div>Loading user data...</div>;return <div>{user.name}</div>;}// 父组件使用示例function App() {const [currentUserId, setCurrentUserId] = useState(1);return (<div><button onClick={() => setCurrentUserId(2)}>Load User 2</button><UserData userId={currentUserId} /></div>);}
  • userId 变化时(如点击按钮切换用户),useEffect 会重新执行,获取新用户数据。
  • 依赖项可以是状态、props 或其他变量,确保副作用与组件状态同步。

四、清理副作用函数

在 React 的 useEffect 中,清理副作用函数(cleanup function)用于在组件卸载或依赖项变化时清除之前的副作用(如取消订阅事件、清除定时器、关闭网络请求等)。以下是几个常见的清理副作用函数的示例:

import { useState, useEffect } from "react";function Child() {useEffect(() => {console.log("child 初始化");return () => {console.log("child 卸载了");};});return <div>child</div>;
}
function App() {const [count, setCount] = useState(0);const [state, setState] = useState(true);useEffect(() => {return () => {console.log("我执行了!!!");};}, [count]);return (<><div><button onClick={() => setCount(count + 1)}>+1</button><button onClick={() => setState(!state)}>显示/隐藏</button></div>{state && <Child />}</>);
}export default App;

在这里插入图片描述

实战案例演示

1. 清除定时器

场景:组件中使用了定时器,需要在组件卸载或依赖项变化时清除定时器。

	import { useState, useEffect } from 'react';function TimerComponent() {const [count, setCount] = useState(0);useEffect(() => {const timer = setInterval(() => {setCount((prev) => prev + 1);}, 1000);// 清理函数:清除定时器return () => {clearInterval(timer);};}, []); // 空数组:仅在组件挂载时设置定时;return <div>Count: {count}</div>;}
  • 组件卸载时,clearInterval(timer) 会被调用,避免内存泄漏。

2. 取消网络请求

场景:组件中发起了网络请求,需要在组件卸载或依赖项变化时取消请求。

	import { useState, useEffect } from 'react';function DataFetcher({ userId }) {const [data, setData] = useState(null);useEffect(() => {const abortController = new AbortController();async function fetchData() {try {const response = await fetch(`/api/users/${userId}`, {signal: abortController.signal,});const result = await response.json();setData(result);} catch (error) {if (error.name !== 'AbortError') {console.error('Fetch error:', error);}}}fetchData();// 清理函数:取消请求return () => {abortController.abort();};}, [userId]); // 依赖项:userId 变化时重新执行if (!data) return <div>Loading...</div>;return <div>{JSON.stringify(data)}</div>;}

总结

useEffect 是 React 函数组件中管理副作用的强大工具,但需要开发者深入理解其工作原理和潜在问题。通过合理使用依赖项、清理函数和函数式更新,可以避免常见的陷阱,写出高效、稳定的代码。

希望本文能帮助你更好地掌握 useEffect,并在实际项目中灵活运用!如果有任何疑问或补充,欢迎在评论区留言讨论。 🚀

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

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

相关文章

Ubuntu 更改 Nginx 版本

将 1.25 降为 1.18 先卸载干净 # 1. 完全卸载当前Nginx sudo apt purge nginx nginx-common nginx-core# 2. 清理残留配置 sudo apt autoremove sudo rm -rf /etc/apt/sources.list.d/nginx*.list修改仓库地址 # 添加仓库&#xff08;通用稳定版仓库&#xff09; codename$(…

如何在 Windows 10 或 11 中安装 PowerShellGet 模块?

PowerShell 是微软在其 Windows 操作系统上提供的强大脚本语言,可用于通过命令行界面自动化各种任务,适用于 Windows 桌面或服务器环境。而 PowerShellGet 是 PowerShell 中的一个模块,提供了用于从各种来源发现、安装、更新和发布模块的 cmdlet。 本文将介绍如何在 PowerS…

NBA足球赛事直播源码体育直播M33模板赛事源码

源码名称&#xff1a;体育直播赛事扁平自适应M33直播模板源码 开发环境&#xff1a;帝国cms7.5 空间支持&#xff1a;phpmysql 带软件采集&#xff0c;可以挂着自动采集发布&#xff0c;无需人工操作&#xff01; 演示地址&#xff1a;NBA足球赛事直播源码体育直播M33模板赛事…

【Python】魔法方法是真的魔法! (第二期)

还不清楚魔术方法&#xff1f; 可以看看本系列开篇&#xff1a;【Python】小子&#xff01;是魔术方法&#xff01;-CSDN博客 【Python】魔法方法是真的魔法&#xff01; &#xff08;第一期&#xff09;-CSDN博客 在 Python 中&#xff0c;如何自定义数据结构的比较逻辑&…

Qt 强大的窗口停靠浮动

1、左边&#xff1a; 示例代码&#xff1a; CDockManager::setConfigFlags(CDockManager::DefaultOpaqueConfig); CDockManager::setConfigFlag(CDockManager::FocusHighlighting, true); dockManager new CDockManager(this); // Disabling the Internal Style S…

Linux进程异常退出排查指南

在 Linux 中&#xff0c;如果进程无法正常终止&#xff08;如 kill 命令无效&#xff09;或异常退出&#xff0c;可以按照以下步骤排查和解决&#xff1a; 1. 常规终止进程 尝试普通终止&#xff08;SIGTERM&#xff09; kill PID # 发送 SIGTERM 信号&#xff08;…

使用tensorRT10部署低光照补偿模型

1.低光照补偿模型的简单介绍 作者介绍一种Zero-Reference Deep Curve Estimation (Zero-DCE)的方法用于在没有参考图像的情况下增强低光照图像的效果。 具体来说&#xff0c;它将低光照图像增强问题转化为通过深度网络进行图像特定曲线估计的任务。训练了一个轻量级的深度网络…

SLAM定位常用地图对比示例

序号 地图类型 概述 1 格栅地图 将现实环境栅格化,每一个栅格用 0 和 1 分别表示空闲和占据状态,初始化为未知状态 0.5 2 特征地图 以点、线、面等几何特征来描绘周围环境,将采集的信息进行筛选和提取得到关键几何特征 3 拓扑地图 将重要部分抽象为地图,使用简单的图形表示…

【图像生成1】Latent Diffusion Models 论文学习笔记

一、背景 本文主要记录一下使用 LDMs 之前&#xff0c;学习 LDMs 的过程。 二、论文解读 Paper&#xff1a;[2112.10752] High-Resolution Image Synthesis with Latent Diffusion Models 1. 总体描述 LDMs 将传统 DMs 在高维图像像素空间&#xff08;Pixel Space&#x…

通信安全堡垒:profinet转ethernet ip主网关提升冶炼安全与连接

作为钢铁冶炼生产线的安全检查员&#xff0c;我在此提交关于使用profinet转ethernetip网关前后对生产线连接及安全影响的检查报告。 使用profinet转ethernetip网关前的情况&#xff1a; 在未使用profinet转ethernetip网关之前&#xff0c;我们的EtherNet/IP测温仪和流量计与PR…

TIFS2024 | CRFA | 基于关键区域特征攻击提升对抗样本迁移性

Improving Transferability of Adversarial Samples via Critical Region-Oriented Feature-Level Attack 摘要-Abstract引言-Introduction相关工作-Related Work提出的方法-Proposed Method问题分析-Problem Analysis扰动注意力感知加权-Perturbation Attention-Aware Weighti…

day 20 奇异值SVD分解

一、什么是奇异值 二、核心思想&#xff1a; 三、奇异值的主要应用 1、降维&#xff1a; 2、数据压缩&#xff1a; 原理&#xff1a;图像可以表示为一个矩阵&#xff0c;矩阵的元素对应图像的像素值。对这个图像矩阵进行 SVD 分解后&#xff0c;小的奇异值对图像的主要结构贡…

符合Python风格的对象(对象表示形式)

对象表示形式 每门面向对象的语言至少都有一种获取对象的字符串表示形式的标准方 式。Python 提供了两种方式。 repr()   以便于开发者理解的方式返回对象的字符串表示形式。str()   以便于用户理解的方式返回对象的字符串表示形式。 正如你所知&#xff0c;我们要实现_…

springboot配置tomcat端口的方法

在Spring Boot中配置Tomcat端口可通过以下方法实现&#xff1a; 配置文件方式 properties格式 在application.properties中添加&#xff1a;server.port8081YAML格式 在application.yml中添加&#xff1a;server:port: 8082多环境配置 创建不同环境的配置文件&#xff08;如app…

DeepSeek指令微调与强化学习对齐:从SFT到RLHF

后训练微调的重要性 预训练使大模型获得丰富的语言和知识表达能力,但其输出往往与用户意图和安全性需求不完全匹配。业内普遍采用三阶段训练流程:预训练 → 监督微调(SFT)→ 人类偏好对齐(RLHF)。预训练阶段模型在大规模语料上学习语言规律;监督微调利用人工标注的数据…

Maven 插件扩展点与自定义生命周期

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

ecmascript 第6版特性 ECMA-262 ES6

https://blog.csdn.net/zlpzlpzyd/article/details/146125018 在之前写的文章基础上&#xff0c;ES6在export和import的基础外&#xff0c;还有如下特性 特性说明let/const块级作用域变量声明>箭头函数Promise异步编程

CT重建笔记(五)—2D平行束投影公式

写的又回去了&#xff0c;因为我发现我理解不够透彻&#xff0c;反正想到啥写啥&#xff0c;尽量保证内容质量好简洁易懂 2D平行束投影公式 p ( s , θ ) ∫ ∫ f ( x , y ) δ ( x c o s θ y s i n θ − s ) d x d y p(s,\theta)\int \int f(x,y)\delta(x cos\theta ysi…

记一次缓存填坑省市区级联获取的操作

先说缓存是什么&#xff1f; 缓存主要是解决高并发&#xff0c;大数据场景下&#xff0c;热点数据快速访问。缓存的原则首先保证数据的准确和最终数据一致&#xff0c;其次是距离用户越近越好&#xff0c;同步越及时越好。 再说我们遇到的场景&#xff1a; 接手项目后&#…

无法加载文件 E:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本

遇到“无法加载文件 E:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本”这类错误&#xff0c;通常是因为你的 PowerShell 执行策略设置为不允许运行脚本。在 Windows 系统中&#xff0c;默认情况下&#xff0c;出于安全考虑&#xff0c;PowerShell 可能会阻止运行未…