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

【React】闭包陷阱

所谓 React 中的闭包陷阱(Closure Trap),其实是 函数组件里的事件回调或副作用中,引用了过期的 state 或 props,导致逻辑异常。


🔹 1. 为什么 React 里会有闭包陷阱?

  • React 函数组件 本质上是一个 render 函数
  • 每次渲染都会生成新的 props / state,以及新的 函数作用域
  • 如果某个回调函数(比如事件处理函数、setTimeout 里的回调、useEffect 里的函数)引用了旧的 state/props,就会形成一个 闭包,而这个闭包“锁死”了旧的值。

🔹 2. 典型例子

import React, { useState } from "react";export default function Counter() {const [count, setCount] = useState(0);function handleClick() {setTimeout(() => {// ❌ 这里会“捕获”当时的 countalert(count);}, 3000);}return (<div><p>{count}</p><button onClick={() => setCount(count + 1)}>+1</button><button onClick={handleClick}>Show Count (after 3s)</button></div>);
}

👉 如果你点了两次 +1(count=2),再点 Show Count,等 3 秒后 alert 出来的却可能是 旧值 0/1

原因:handleClick 生成的闭包里,保存的 count 还是旧的。


🔹 3. 解决办法

✅ 方法一:使用函数式更新(推荐)

setCount(prev => prev + 1);

👉 不依赖闭包里的 count,而是总能拿到最新的值。


✅ 方法二:依赖数组正确写法(useEffect

useEffect(() => {const timer = setInterval(() => {console.log(count); // 每次渲染后闭包更新,打印最新值}, 1000);return () => clearInterval(timer);
}, [count]); // 依赖 count

👉 保证每次 count 变了,副作用都能捕获到新值。


✅ 方法三:使用 useRef 保存最新值

const countRef = useRef(count);useEffect(() => {countRef.current = count; // 每次更新时刷新 ref
});function handleClick() {setTimeout(() => {alert(countRef.current); // ✅ 永远能拿到最新值}, 3000);
}

👉 ref 不会因为重新渲染而丢失,适合存放“跨渲染保持的最新值”。


🔹 4. 总结

  • 闭包陷阱原因:函数组件每次渲染都会创建新的作用域,回调函数可能捕获旧的 props/state。

  • 常见场景setTimeoutsetInterval、事件回调、异步请求回调、useEffect

  • 解决办法

    1. 函数式更新 setState(prev => ...)
    2. 正确声明依赖(useEffect
    3. 使用 useRef 存最新值

文章转载自:

http://itAClKic.LqLfj.cn
http://s0RSKjHF.LqLfj.cn
http://oT9xtCFd.LqLfj.cn
http://h4uTlyr8.LqLfj.cn
http://MWbtJlpq.LqLfj.cn
http://uyAzP19z.LqLfj.cn
http://03ZQhZJ5.LqLfj.cn
http://cz6O824V.LqLfj.cn
http://Y6wnGLjV.LqLfj.cn
http://iFVQaLr7.LqLfj.cn
http://cKZPTyAQ.LqLfj.cn
http://7mlVeU6M.LqLfj.cn
http://jLsJxYLt.LqLfj.cn
http://Cs8pZK4I.LqLfj.cn
http://i5VH92Xi.LqLfj.cn
http://JY9koYPY.LqLfj.cn
http://GXQrciQK.LqLfj.cn
http://mhWv8Y7J.LqLfj.cn
http://SJT712Al.LqLfj.cn
http://x171UxIs.LqLfj.cn
http://QfPvLzOu.LqLfj.cn
http://cClEzRZe.LqLfj.cn
http://kr8ocsl8.LqLfj.cn
http://GDDpPJs8.LqLfj.cn
http://2XibtVft.LqLfj.cn
http://B2nxaMAb.LqLfj.cn
http://URqvaH6v.LqLfj.cn
http://ZsjY0Fmp.LqLfj.cn
http://6SRqJjl3.LqLfj.cn
http://ATSPbTSP.LqLfj.cn
http://www.dtcms.com/a/384937.html

相关文章:

  • 4.RocketMQ集群高级特性
  • 周选择日历组件
  • Golang引用类型
  • Go的Gob编码介绍与使用指南
  • Golang语言入门篇001_Golang简介
  • Kafka消息队列进阶:发送策略与分区算法优化指南
  • 台积电生态工程深度解析:从晶圆厂到蜂巢的系统架构迁移
  • 机器学习-网络架构搜索
  • 邪修实战系列(5)
  • 突破限制:Melody远程音频管理新体验
  • 深入解析Seata:一站式分布式事务解决方案
  • static_cast:C++类型系统的“正经翻译官”
  • Python面试题及详细答案150道(126-135) -- 数据库交互篇
  • 【新书预告】《大模型应用开发》
  • MySQL 视图的创建与查看:从基础操作到核心技巧
  • 企业内容管理(ECM)软件推荐与应用解析
  • 利用postgres_proto和pgproto配合验证测试postgres协议
  • 联咏nt98568点亮sensor步骤
  • 大模型操作SQL查询Text2SQL
  • 风力发电乙级资质需要哪些人员配备
  • 【JavaScript】实现一个高精度的定时器
  • 无偏估计-
  • SQL-流程控制函数
  • TNNLS-2015《Linear-Time Subspace Clustering via Bipartite Graph Modeling》
  • 线性代数 · 行列式 | 子式 / 主子式 / 顺序主子式 / 余子式 / 代数余子式
  • LLM的MTP论文阅读
  • 软考-系统架构设计师 软件工程详细讲解
  • MATLAB 实现基于 GMM-HMM的语音识别系统
  • Day24_【深度学习(4)—PyTorch使用—张量的数值计算】
  • 2019年下半年 系统架构设计师 综合知识