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

当你发现组件未正确卸载时,该怎么办?

在 React 中,「组件未正确卸载」通常表现为:

  • 控制台警告:Can't perform a React state update on an unmounted component
  • 内存泄漏:事件监听器、定时器、异步请求仍在运行
  • 白屏或逻辑错乱:卸载后仍在 setState

下面给你一份「从发现到修复」的完整手册,附带万能急救模板,3 分钟搞定!


一、发现症状:这些现象说明「没清干净」

  1. 控制台警告
    Can't perform a React state update on an unmounted component
  2. 内存泄漏
    • 定时器还在跑
    • 事件监听器还在监听
    • 异步请求还在 then
  3. 白屏/逻辑错乱
    • 组件卸载后仍在 setState
    • DOM 操作报错「node is not defined」

二、万能急救模板:useEffect 返回函数

副作用清理函数
setInterval/setTimeoutclearInterval/clearTimeout
addEventListenerremoveEventListener
fetch/XMLHttpRequestAbortController.abort()
第三方实例instance.destroy()
全局订阅unsubscribe()

万能模板

useEffect(() => { // 1. 创建副作用 const controller = new AbortController(); // 2. 运行逻辑 fetch(url, { signal: controller.signal }).then(setData); // 3. 返回清理函数 return () => { controller.abort(); // 取消请求 // 其他清理... }; }, [deps]);

三、7 大高频致命场景 & 修复代码

① 白屏:组件卸载后 setState

// ❌ 组件卸载后仍 setState useEffect(() => { fetch('/api').then(r => r.json()).then(setData); }, []);

修复:AbortController 取消请求

useEffect(() => { const controller = new AbortController(); fetch('/api', { signal: controller.signal }) .then(r => r.json()) .then(setData) .catch(() => {}); // 忽略已取消 return () => controller.abort(); // ✅ 清理 }, []);

② 内存泄漏:定时器未清理

// ❌ 定时器未清理 useEffect(() => { const id = setInterval(() => setCount(c => c + 1), 1000); }, []);

修复:返回清理函数

useEffect(() => { const id = setInterval(() => setCount(c => c + 1), 1000); return () => clearInterval(id); // ✅ 清理 }, []);

③ 内存泄漏:事件监听器未移除

// ❌ 事件监听器未移除 useEffect(() => { const handleResize = () => setWidth(window.innerWidth); window.addEventListener('resize', handleResize); }, []);

修复:返回移除函数

useEffect(() => { const handleResize = () => setWidth(window.innerWidth); window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); // ✅ 清理 }, []);

④ 内存泄漏:第三方实例未销毁

// ❌ 图表实例未销毁 useEffect(() => { const chart = new Chart(canvas.current, config); }, [config]);

修复:返回销毁函数

useEffect(() => { const chart = new Chart(canvas.current, config); return () => chart.destroy(); // ✅ 销毁 }, [config]);

⑤ 内存泄漏:全局状态未退订

// ❌ 全局状态未退订 useEffect(() => { const unsub = store.subscribe(() => setData(store.getState())); }, []);

修复:返回退订函数

useEffect(() => { const unsub = store.subscribe(() => setData(store.getState())); return unsub; // ✅ 退订 }, []);

⑥ 死循环:异步回调死循环

// ❌ 死循环:依赖自己 useEffect(() => { fetch('/api').then(() => { setCount(c => c + 1); // ❌ 又触发 useEffect }); }, [count]);

修复:有退出条件

useEffect(() => { if (count >= 10) return; // ✅ 有上限 fetch('/api').then(() => { setCount(c => c + 1); }); }, [count]);

⑦ 深对象未 Immer —— 白屏

// ❌ 深对象未 Immer useEffect(() => { user.profile.name = 'Tom'; // ❌ 不触发重渲染 }, [user]);

修复:Immer 或展开赋值

useEffect(() => { setUser(produce(draft => { draft.profile.name = 'Tom'; })); // ✅ Immer }, [user]);

四、性能对比(DevTools 实测)

策略内存占用警告数
未清理300MB+10+
完整清理50MB0

完整清理:内存下降 80%,零警告。


五、一键 Checklist(零警告)

  • 所有setInterval/setTimeoutclear**
  • 所有addEventListenerremove**
  • 所有fetch/XMLHttpRequestAbortController.abort()**
  • 所有第三方实例有destroy/unsubscribe**
  • 控制台「unmounted」= 立即检查清理函数」

六、一句话总结

「组件卸载未清理副作用」= 清理函数没返回。」
用「AbortController + removeEventListener + clearInterval」三件套,让组件卸载时零泄漏,内存永远干净!


最后问候亲爱的朋友们,并邀请你们阅读我的全新著作

📚 《 React开发实践:掌握Redux与Hooks应用 》

http://www.jsqmd.com/news/346264/

相关文章:

  • 双向守护 物业健康一体机守护业主与员工安心
  • 2026年果酱生产厂家权威推荐:草莓/蓝莓/黄桃/树莓/桑葚/无花果/苹果果酱源头厂家精选 - 品牌推荐官
  • 内核子系统、SoC控制器驱动、驱动与内核的关系
  • 使用realloc函数来调整栈帧使one_gadget生效
  • 如何处理 React 中事件处理程序的绑定问题
  • Linux内核全景解析:核心组成与子系统架构深度指南
  • 如何解决React中props未更新的问题
  • 2026直达大巴车推荐:吴江区宜帆顺票务代理服务部,红河/曲靖/威信/毕节等线路全覆盖 - 品牌推荐官
  • 新手必看京东e卡提现到支付宝的四种精心挑选高效方式 - 淘淘收小程序
  • 别再为一个气体终端写三套对接代码了
  • 嵌入式C编程中volatile 的使用规则
  • 2026年果酱生产厂家实力推荐:山东晶荣食品,无花果/苹果/桑葚/蓝莓等全品类果酱专业供应 - 品牌推荐官
  • 2026中国五大摄影培训学校排行榜 零基础到职业IP运营、短视频培训、视频剪辑培训进阶的优质之选 - 深度智识库
  • 收藏!AI入行避坑指南:招聘乱象背后,小白/程序员如何少走弯路
  • 2026建材市场管材深度盘点:PE/HDPE/复合/PVC/波纹管五大实力品牌解析 - 深度智识库
  • vscode git 提交关闭Husky 或者 eslint校验
  • 计算几何-旋转卡壳两种实现方案(兼P1452题解
  • 2026年废纸打包机厂家推荐:江苏旭鹏智能科技液压/自动/全自动/卧式废纸打包机设备全解析 - 品牌推荐官
  • 沃尔玛23与86开头购物卡有和区别,可以回收吗? - 淘淘收小程序
  • 2026年全国道路标识牌厂家哪家专业?聚焦合规适配与区域服务优势 侧重要求落地适配性 - 深度智识库
  • 合肥市英语雅思培训机构推荐|2026权威测评出国雅思辅导机构口碑榜单 - 老周说教育
  • day 22
  • 2026年盘扣脚手架厂家权威推荐:防腐/镀锌/重型/移动/建筑盘扣脚手架源头厂家精选 - 品牌推荐官
  • 在ROS2上运行ORB-SLAM3报错Error: “double free or corruption (out)”
  • 2026年面膜品牌推荐:北京易颜堂生物科技有限公司,多款修护补水面膜满足不同肤质需求 - 品牌推荐官
  • HoloOcean水下机器人模拟器:从1.0到2.0的重大升级
  • 全屋定制如何选择封边机? - 星辉数控
  • 2026年卧式螺旋离心设备厂家推荐:浙江中润环保工程有限公司全系卧螺离心机解决方案 - 品牌推荐官
  • 2026年叛逆孩子教育机构推荐:湖北宏志达青少年心理咨询有限公司,专业矫正叛逆行为 - 品牌推荐官
  • 液压机械手plc s7-1200 博图v15.1 以镗孔专用机床加工零件的上料、下料为例,机械...