第四节:React Hooks进阶篇-useEffect依赖项为空数组[]与不写的区别

陷阱题:闭包问题、Stale Closure举例

一、依赖项为空数组[]与不写的核心区别
行为空数组[]不写依赖项
执行时机仅在组件挂载时执行一次(类似componentDidMount组件每次渲染后都执行(类似componentDidUpdate
更新触发条件永不触发(除非组件卸载后重新挂载)任何状态或属性变化都会触发
清理函数执行时机仅在组件卸载时执行一次每次重新渲染前都会执行清理函数

二、闭包陷阱(Stale Closure)示例
案例1:定时器中的旧值引用
function Counter() {const [count, setCount] = useState(0);useEffect(() => {const timer = setInterval(() => {// 闭包陷阱:始终引用初始值0console.log(count); }, 1000);return () => clearInterval(timer);}, []); // 依赖项为空数组return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}

问题:定时器回调函数中的count始终是初始值0,因为闭包捕获了初始渲染时的状态。
原因:空数组依赖项导致useEffect仅执行一次,内部闭包未更新。

案例2:依赖项缺失导致无限循环
useEffect(() => {setCount(count + 1); // 未设置依赖项,每次渲染触发更新
}); 

结果:组件陷入无限渲染循环。


三、闭包问题的解决方案
方案1:正确设置依赖项
useEffect(() => {const timer = setInterval(() => {console.log(count); // 每次count变化时获取最新值}, 1000);return () => clearInterval(timer);
}, [count]); // 依赖项包含count

原理:依赖项变化时,重新生成闭包函数。

方案2:使用useRef绕过闭包
const countRef = useRef(count);
useEffect(() => {countRef.current = count; // 手动同步最新值到ref
});useEffect(() => {const timer = setInterval(() => {console.log(countRef.current); // 通过ref获取最新值}, 1000);return () => clearInterval(timer);
}, []);

优势:避免依赖项导致定时器频繁重置。

方案3:函数式更新状态
useEffect(() => {const timer = setInterval(() => {setCount(c => c + 1); // 函数式更新,避免依赖旧值}, 1000);return () => clearInterval(timer);
}, []);

原理:通过函数参数获取最新状态值,无需依赖项。


四、最佳实践与性能优化
  1. 依赖项规则:确保所有引用的外部变量(包括propsstate)都出现在依赖数组中。
  2. 避免对象/数组依赖:直接传递对象属性或使用useMemo优化引用类型。
  3. 并发模式兼容:React 18中,useEffect可能被中断渲染,优先使用useLayoutEffect处理DOM同步操作。

五、总结对比表
场景空数组[]无依赖项
典型用途初始化请求、一次性订阅响应式DOM操作、全局事件监听
闭包风险高(依赖旧值)低(每次更新生成新闭包)
性能影响低(仅执行一次)高(频繁触发)

通过合理选择依赖项策略,可显著提升组件性能和逻辑健壮性。

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

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

相关文章

【第39节】windows编程:打造MFC版本任务管理器

目录 一、项目概述 二、项目开发的各种功能关键 2.1 进程信息的获取 2.2 线程信息的获取 2.3 进程模块信息的获取 2.3.1 模块快照 2.3.2 枚举模块 2.4 进程堆信息的获取 2.5 窗口信息的获取 2.6 文件信息的获取 2.7 内存信息和CPU占用率的获取 2.7.1 内存信息相关结…

计算轴承|滚动轴承故障频率

一、轴承故障频率概述 在旋转机械故障诊断中&#xff0c;轴承故障频率&#xff08;BPFO、BPFI、BSF、FTF&#xff09;是重要的分析依据。通过计算这些特征频率&#xff0c;可以帮助工程师&#xff1a; 识别轴承故障类型&#xff08;内圈/外圈/滚动体故障&#xff09;制定振动…

【数据结构与算法】ArrayList 和 顺序表

文章目录 &#x1f332;List&#x1f332;1. 线性表&#x1f332;2. 顺序表&#x1f33f;2.1 MyArrayList2.1.1 类中重写所有接口方法1.新增元素2.在pos位置新增元素(指定位置)3.判定是否包含了某个特定元素 4.查找特定元素对应的位置 5.获取pos下标的元素 6.给pos位置的元素替…

OceanBase 推出单机版 ,为中小规模业务提供高性价比方案

近日&#xff0c;OceanBase正式推出了全新的单机版数据库。这款产品基于OceanBase自主研发的单机分布式一体化架构&#xff0c;具有精简的架构设计和出色的兼容性&#xff0c;能够为中小规模业务场景提供高性价比的数据库解决方案&#xff0c;充分满足客户在不同业务规模下的多…

如何在 Vue 3 中实现百度地图位置选择器组件

如何在 Vue 3 中实现百度地图位置选择器组件 前言 在开发前端应用时&#xff0c;地图选择器是一个非常常见的需求。尤其是在一些需要用户选择地址的场景&#xff0c;如电商平台、旅游网站、酒店预定等&#xff0c;百度地图组件能提供准确的地理位置服务。在本文中&#xff0c…

Python中如何用正则表达式精准匹配IP地址?

在网络编程和数据处理时&#xff0c;我们经常需要从文本中提取或验证IP地址。Python的正则表达式(re模块)是完成这个任务的利器。但你知道怎么写才能准确匹配各种合法的IP地址吗&#xff1f;今天我们就来详细探讨这个问题。 为什么需要IP正则表达式&#xff1f; 假设你正在分…

spring--声明式事务

声明式事务 1、回顾事务 要么都成功&#xff0c;要么都失败&#xff01; 事务在项目开发中&#xff0c;十分重要&#xff0c;涉及数据的一致性问题 确保完整性和一致性 事务ACID&#xff1a; 原子性&#xff1a;事务是原子性操作&#xff0c;由一系列动作组成&#xff0c;…

Kotlin 学习-集合

/*** kotlin 集合* List:是一个有序列表&#xff0c;可通过索引&#xff08;下标&#xff09;访问元素。元素可以在list中出现多次、元素可重复* Set:是元素唯一的集合。一般来说 set中的元素顺序并不重要、无序集合* Map:&#xff08;字典&#xff09;是一组键值对。键是唯一的…

WPF 五子棋项目文档

WPF 五子棋项目文档 1. 项目概述 本项目是一个使用 Windows Presentation Foundation (WPF) 技术栈和 C# 语言实现的桌面版五子棋&#xff08;Gomoku&#xff09;游戏。它遵循 MVVM&#xff08;Model-View-ViewModel&#xff09;设计模式&#xff0c;旨在提供一个结构清晰、可…

计算机操作系统——死锁(详细解释和处理死锁)

系列文章目录 计算机操作系统-计算机系统中的死锁 文章目录 系列文章目录前言一、资源问题&#xff1a; 计算机系统当中的死锁&#xff1a; 二、死锁的定义、必要条件和处理方法&#xff1a; 1.死锁的定义&#xff1a;2.产生死锁的必要条件&#xff1a;3.处理死锁的方法&#…

Springboot项目正常启动,访问资源却出现404错误如何解决?

我在自己的springboot项目中的启动类上同时使用了SprinBootApplication和ComponentScan注解, 虽然项目能够正常启动,但是访问资源后,返回404错误,随后在启动类中输出bean,发现controller创建失败: 而后我将ComponentScan去掉后资源就能访问到了. 原因 SprinBootApplication本身…

第十五届蓝桥杯C/C++B组省赛真题讲解(分享去年比赛的一些真实感受)

试题A——握手问题 一、解题思路 直接用高中学的排列组合思路 二、代码示例 #include<bits/stdc.h> using namespace std; int fun(int n) {int sum0;for(int i0;i<n;i){for(int ji1;j<n;j)sum; } return sum; } int main() {cout<<fun(50)-fun(7); }三、…

动态规划(6)——01背包问题

欢迎来到博主的专栏&#xff1a;算法解析 博主ID&#xff1a;代码小号 文章目录 牛客网——【模板】01背包题目解析题目1算法原理题目1题解代码。问题2算法原理问题2题解代码01背包问题的滚动数组优化 牛客网——【模板】01背包 题目解析 关于I/O相关的东西博主就不多赘述了&a…

TQTT_KU5P开发板教程---实现流水灯

文档实现功能介绍 本文档是学习本开发板的基础&#xff0c;通过设置计数器使led0到led7依次闪烁&#xff0c;让用户初步认识vivado基本的开发流程以及熟悉项目的创建。本开发板的所有教程所使用的软件都是vivado2024.1版本的。可以根据网上的教程下载与安装。 硬件资源 此次教程…

Spring 中的 @Cacheable 缓存注解

1 什么是缓存 第一个问题&#xff0c;首先要搞明白什么是缓存&#xff0c;缓存的意义是什么。 对于普通业务&#xff0c;如果要查询一个数据&#xff0c;一般直接select数据库进行查找。但是在高流量的情况下&#xff0c;直接查找数据库就会成为性能的瓶颈。因为数据库查找的…

SEER: Self-Aligned Evidence Extraction for Retrieval-AugmentedGeneration

一、动机 如何从检索到的段落中提取证据&#xff0c;以降低计算成本并提升最终的RAG性能&#xff0c;然而这一问题仍然具有挑战性。 现有方法 严重依赖于基于启发式的增强&#xff0c;面临以下几个问题&#xff1a; &#xff08;1&#xff09;由于手工制作的上下文过滤&…

毫米波测试套装速递!高效赋能5G/6G、新材料及智能超表面(RIS)研发

德思特&#xff08;Tesight&#xff09;作为全球领先的测试测量解决方案提供商&#xff0c;始终致力于为前沿技术研发提供高精度、高效率的测试工具。 针对毫米波技术在高频通信、智能超表面&#xff08;RIS&#xff09;、新材料等领域的快速应用需求&#xff0c;我们推出毫米…

三维激光测量助力企业检测效率提升3倍

智能制造与数字化浪潮席卷下&#xff0c;三维扫描技术已成为工业检测领域不可或缺的工具。面对传统检测手段的精度瓶颈与效率局限&#xff0c;三维扫描仪&#xff0c;以毫米级精度、非接触式测量与超高速扫描三大核心优势&#xff0c;为汽车制造、航空航天、消费电子等行业的品…

SQL:Normalization(范式化)

目录 Normalization&#xff08;范式化&#xff09; 为什么需要 Normalization&#xff1f; &#x1f9e9; 表格分析&#xff1a; 第一范式&#xff08;1NF&#xff09; 什么是第一范式&#xff08;First Normal Form&#xff09;&#xff1f; 第二范式&#xff08;2NF&am…

#MES系统运维问题分析思路

一套适用于90% MES运维现场问题的排查分析思维模型&#xff0c;叫做&#xff1a; &#x1f50d; MES系统问题分析七步法&#xff08;现场实战适用&#xff09; ✅ 第一步&#xff1a;明确问题现象&#xff08;What&#xff09; 问题要说清楚&#xff0c;“不能操作”这种模糊描…