You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用TypeScript+Firestore+React Router时React内存泄漏问题如何解决

问题根源

你遇到的警告来自两个可优化点:

  1. Firestore的onSnapshot实时监听没有在组件卸载时取消,当你删除通知数据后,监听回调依然会触发并执行setAlertNotifcations更新状态,此时组件已经跳转卸载,就会触发内存泄漏警告。
  2. 你之前编写useEffect清理逻辑时写法错误,导致TypeScript类型报错。

修复方案

1. 正确添加快照监听的清理逻辑

修改你的useEffect代码如下即可,不需要改动loadAlerts的现有逻辑:

useEffect(() => {
    const unsubscribe = loadAlerts();
    console.log(alertNotifications);
    // 组件卸载时自动调用取消监听
    return () => unsubscribe();
}, [loadAlerts]);

注意要把loadAlerts加入useEffect的依赖数组,因为你已经用useCallback包裹了它,仅当notifications变化时才会更新,不会造成useEffect重复执行。

2. TypeScript报错原因说明

你遇到的Argument of type '() => () => Unsubscribe' is not assignable to parameter of type 'EffectCallback'报错,是因为你之前的错误写法:

// 错误写法:回调直接返回loadAlerts函数本身,没有执行
useEffect(() => loadAlerts, []);

这种写法下useEffect回调的返回值是loadAlerts函数(类型为() => Unsubscribe),不符合useEffect要求的返回void或者() => void类型的清理函数,按照上面给出的正确写法执行loadAlerts拿到返回的unsubscribe再返回清理逻辑即可解决类型报错。

可选优化(非必须)

如果还有异步事务执行完成后要做状态更新的场景,可以加一个挂载状态标记避免更新已卸载组件:

const isMounted = useRef(true);
useEffect(() => {
  isMounted.current = true;
  return () => {
    isMounted.current = false;
  }
}, []);

// 之后所有异步回调里更新状态前先判断挂载状态
if (isMounted.current) {
  setXXX(xxx);
}

内容的提问来源于stack exchange,提问作者tim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 22:06:06