使用TypeScript+Firestore+React Router时React内存泄漏问题如何解决
问题根源
你遇到的警告来自两个可优化点:
- Firestore的
onSnapshot实时监听没有在组件卸载时取消,当你删除通知数据后,监听回调依然会触发并执行setAlertNotifcations更新状态,此时组件已经跳转卸载,就会触发内存泄漏警告。 - 你之前编写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
相关产品推荐
相关产品推荐

