深入解析 React 的 useEffect:从入门到实战
文章目录
- 前言
- 一、为什么需要 `useEffect`?
- 核心作用:
- 二、`useEffect` 的基础用法
- 1. 基本语法
- 2. 依赖项数组的作用
- 三、依赖项数组演示
- 1. 空数组 `[]`:
- 2.无依赖项(空)
- 3.有依赖项
- 四、清理副作用函数
- 实战案例演示
- 1. 清除定时器
- 2. 取消网络请求
- 总结
前言
在 React 函数组件中,useEffect
是处理副作用(Side Effects)的核心 Hook。无论是数据获取、订阅事件、手动操作 DOM,还是其他异步任务,useEffect
都能帮助开发者优雅地管理这些副作用。然而,它的使用场景复杂且容易踩坑。本文将带你从基础到实战,全面掌握 useEffect
的核心原理和最佳实践。
一、为什么需要 useEffect
?
在类组件中,副作用通常通过生命周期方法(如 componentDidMount
、componentDidUpdate
、componentWillUnmount
)管理。但在函数组件中,由于没有生命周期方法,React 提供了 useEffect
来统一处理这些场景。
核心作用:
- 数据获取:在组件挂载后从 API 获取数据。
- 订阅/取消订阅:如 WebSocket、事件监听等。
- 手动操作 DOM:如调整滚动位置、聚焦输入框。
- 清理副作用:避免内存泄漏或重复操作。
二、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,并在实际项目中灵活运用!如果有任何疑问或补充,欢迎在评论区留言讨论。 🚀
相关文章:

深入解析 React 的 useEffect:从入门到实战
文章目录 前言一、为什么需要 useEffect?核心作用: 二、useEffect 的基础用法1. 基本语法2. 依赖项数组的作用 三、依赖项数组演示1. 空数组 []:2.无依赖项(空)3.有依赖项 四、清理副作用函数实战案例演示1. 清除定时器…...

通过Ollama读取模型
通过Ollama读取模型 前言一、查看本地Ollama上有哪些模型二、调用bge-m3模型1、调用模型2、使用bge-m3进行相似度比较 三、调用大模型 前言 手动下载和加载大模型通常需要复杂的环境配置,而使用Ollama可以避免这一问题。本文将介绍如何调用Ollama上的模型。 一、查…...
C#控制流
🧩 一、控制流概述 C# 中的控制流语句用于根据条件或循环执行代码块。它们是程序逻辑的核心部分。 ✅ 二、1. if、else if、else int score 85;if (score > 90) {Console.WriteLine("优秀"); } else if (score > 60) {Console.WriteLine("及…...

永久免费,特殊版本!
随着大家审美的不断提升,无论是社交平台的日常分享还是特定场景的图像展示,人们对图像质量的要求都日益严苛。为了呈现更完美的视觉效果,许多小伙伴都会对原始图像进行精细化的后期处理,其中复杂背景抠图、光影调整、色彩校正等专…...

Canva 推出自有应用生成器以与 Bolt 和 Lovable 竞争
AI 目前是一个巨大的市场,每个人都想从中分一杯羹。 即使是 Canva,这个以拖放图形设计而闻名的流行设计平台,也在其 Canva Create 2025 活动中发布了自己版本的代码生成器,加入了 AI 竞赛。 但为什么一个以设计为先的平台会提供代码生成工具呢? 乍看之下,这似乎有些不…...

Matrix-Game:键鼠实时控制、实时生成的游戏生成模型(论文代码详细解读)
1.简介 本文介绍了一种名为Matrix-Game的交互式世界基础模型,专门用于可控的游戏世界生成。 Matrix-Game通过一个两阶段的训练流程来实现:首先进行大规模无标签预训练以理解环境,然后进行动作标记训练以生成交互式视频。为此,研…...

MySQL 5.7在CentOS 7.9系统下的安装(下)——给MySQL设置密码
新下载下来的MySQL,由于没有root密码,(1)所以如果我们希望登陆mysql,得给mysql的root账户设置密码,或者另一方面来说,(2)未来如果你忘记root密码了,也能通过这…...

机器学习笔记2
5 TfidfVectorizer TF-IDF文本特征词的重要程度特征提取 (1) 算法 词频(Term Frequency, TF), 表示一个词在当前篇文章中的重要性 逆文档频率(Inverse Document Frequency, IDF), 反映了词在整个文档集合中的稀有程度 (2) API sklearn.feature_extraction.text.TfidfVector…...
AgentCPM-GUI,清华联合面壁智能开源的端侧GUI智能体模型
AgentCPM-GUI是什么 AgentCPM-GUI 是由清华大学与面壁智能团队联合开发的一款开源端侧图形用户界面(GUI)代理,专为中文应用进行优化。基于 MiniCPM-V 模型(80 亿参数),该系统能够接收智能手机的屏幕截图&a…...
Go语言实现链式调用
在 Go 语言中实现链式调用(Method Chaining),可以通过让每个方法返回对象本身(或对象的指针)来实现。这样每次方法调用后可以继续调用其他方法。 示例:实现字符串的链式操作 假设你想对一个字符串连续执行…...

重排序模型解读 mxbai-rerank-base-v2 强大的重排序模型
mxbai-rerank-base-v2 强大的重排序模型 模型介绍benchmark综合评价安装 模型介绍 mxbai-rerank-base-v2 是 Mixedbread 提供的一个强大的重排序模型,旨在提高搜索相关性。该模型支持多语言,特别是在英语和中文方面表现出色。它还支持代码和 SQL 排序&a…...

期望是什么:(无数次的均值,结合概率)21/6=3.5
https://seeing-theory.brown.edu/basic-probability/cn.html 期望是什么:(无数次的均值,结合概率)21/6=3.5 一、期望(数学概念) 在概率论和统计学中,**期望(Expectation)**是一个核心概念,用于描述随机变量的长期平均取值,反映随机变量取值的集中趋势。 (一…...

uniapp-vue3项目中引入高德地图的天气展示
前言: uniapp-vue3项目中引入高德地图的天气展示 效果: 操作步骤: 1、页面上用定义我们的 当前天气信息:<view></view> 2、引入我们的map文件 <script setup>import amapFile from ../../libs/amap-wx.js …...
容器化-k8s-介绍及下载安装教程
一、K8s 概念 官网地址: https://kubernetes.io/zh/docs/tutorials/kubernetes-basics/ 1、含义 Kubernetes 是一个开源的容器编排引擎,用于自动化部署、扩展和管理容器化应用程序。它可以将多个容器组合成一个逻辑单元,实现对容器的集中管理和调度,从而简化复杂应用的部…...

lc42接雨水
1.原题 42. 接雨水 - 力扣(LeetCode) 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 2.题目解析 这一题是经常被考到的一道算法题,其中最简单最好用的方法就是双指…...

通义千问-langchain使用构建(三)
目录 序言docker 部署xinference1WSL环境docker安装2拉取镜像运行容器3使用的界面 本地跑chatchat1rag踩坑2使用的界面2.1配置个前置条件然后对话2.2rag对话 结论 序言 在前两天的基础上,将xinference调整为wsl环境,docker部署。 然后langchain chatcha…...
uniapp自动构建pages.json的vite插件
对于 uniapp 来说,配置 pages.json 无疑是最繁琐的事情,具有以下缺点: 冗长,页面很多时 pages 内容会很长难找,有时候因为内容很长,导致页面配置比较难找,而且看起来比较凌乱json弊端ÿ…...

系统漏洞扫描服务:维护网络安全的关键与服务原理?
系统漏洞扫描服务是维护网络安全的关键措施,能够迅速发现系统中的潜在风险,有效预防可能的风险和损失。面对网络攻击手段的日益复杂化,这一服务的重要性日益显著。 服务原理 系统漏洞扫描服务犹如一名恪尽职守的安全守护者。它运用各类扫描…...
nlf loss 学习笔记
目录 数据集: 3d 投影到2d 继续求loss reconstruct_absolute 1. 功能概述 2. 参数详解 3. 两种重建模式对比 数据集: agora3 | 5264/5264 [00:00<00:00, 143146.78it/s] behave 37736/37736 [00:00<00:00, 76669.67it/s] mads 32649/3264…...

【Redis】零碎知识点(易忘 / 易错)总结回顾
一、Redis 是一种基于键值对(key-value)的 NoSQL 数据库 二、Redis 会将所有数据都存放在内存中,所以它的读写性能非常惊人 Redis 还可以将内存的数据利用快照和日志的形式保存到硬盘上,这样在发生类似断电或者机器故障时…...

基于three.js 全景图片或视频开源库Photo Sphere Viewer
Photo Sphere Viewer 是一个基于 JavaScript 的开源库,专门用于在网页上展示 360 全景图片或视频。它提供了丰富的交互功能,允许用户通过鼠标、触摸屏或陀螺仪来浏览全景内容,适用于旅游、房地产、虚拟现实、教育等多个领域。 主要特点 多种…...

LangPDF: Empowering Your PDFs with Intelligent Language Processing
LangPDF: Empowering Your PDFs with Intelligent Language Processing Unlock Global Communication: AI-Powered PDF Translation and Beyond In an interconnected world, seamless multilingual document management is not just an advantage—it’s a necessity. LangP…...

OpenVLA (2) 机器人环境和环境数据
文章目录 [TOC](文章目录) 前言1 BridgeData V21.1 概述1.2 硬件环境 2 数据集2.1 场景与结构2.2 数据结构2.2.1 images02.2.2 obs_dict.pkl2.2.3 policy_out.pkl 3 close question3.1 英伟达环境3.2 LIBERO 环境更适合仿真3.3 4090 运行问题 前言 按照笔者之前的行业经验, 数…...

代码复现5——VLMaps
项目地址 1 Setup # 拉取VLMaps仓库,成功运行后会在主目录生成文件夹vlmapsgit clone https://github.com/vlmaps/vlmaps.git#通过 conda 创建虚拟环境conda create -n vlmaps python=3.8 -yconda activate vlmaps #激活环境cd vlmaps # 切换到项目文件下bash install.ba…...

Ocean: Object-aware Anchor-free Tracking
领域:Object tracking It aims to infer the location of an arbitrary target in a video sequence, given only its location in the first frame 问题/现象: Anchor-based Siamese trackers have achieved remarkable advancements in accuracy, yet…...

计算机网络(1)——概述
1.计算机网络基本概念 1.1 什么是计算机网络 计算机网络的产生背景 在计算机网络出现之前,计算机之间都是相互独立的,每台计算机只能访问自身存储的数据,无法与其他计算机进行数据交换和资源共享。这种独立的计算机系统存在诸多局限性&#…...

刘家祎双剧收官见证蜕变,诠释多面人生
近期,两部风格迥异的剧集迎来收官时刻,而青年演员刘家祎在《我家的医生》与《无尽的尽头》中的精彩演绎,无疑成为观众热议的焦点。从温暖治愈的医疗日常到冷峻深刻的少年救赎,他以极具张力的表演,展现出令人惊叹的可塑…...

Axure制作可视化大屏动态滚动列表教程
在可视化大屏设计中,动态滚动列表是一种常见且实用的展示方式,能够有效地展示大量信息。本文将详细介绍如何使用Axure制作一个动态滚动的列表展示模块。 一、准备工作 打开Axure软件:确保你已经安装并打开了Axure RP软件。创建新项目&#x…...

MATLAB实现振幅调制(AM调制信号)
AM调制是通信专业非常重要的一个知识点。今天我们使用MATLAB编程实现AM调制。 我们实现输入一个载波信号的频率与调制信号的频率后,再输入调幅度,得到已调信号的波形与包络信号的波形,再使用FFT算法分析出已调信号的频谱图。 源代码&#x…...
LLM-Based Agent综述及其框架学习(五)
文章目录 摘要Abstract1. 引言2. 文本输出3. 工具的使用3.1 理解工具3.2 学会使用工具3.3 制作自给自足的工具3.4 工具可以扩展LLM-Based Agent的行动空间3.5 总结 4. 具身动作5. 学习智能体框架5.1 CrewAI学习进度5.2 LangGraph学习进度5.3 MCP学习进度 参考总结 摘要 本文围绕…...