自定义useIsOnline Hook触发React内存泄漏错误,如何修复?
修复useIsOnline Hook的内存泄漏问题
你遇到的错误根源有两个:
- 异步
fetch请求完成时,组件可能已经卸载,此时调用setOnline会触发已卸载组件的状态更新警告 - 给window绑定的
online/offline事件监听器未在组件卸载时移除,后续事件触发时仍会尝试更新已卸载组件的状态
直接按以下思路修改代码即可解决:
- 给异步请求添加挂载状态判断,避免卸载后更新状态
- 为事件监听的
useEffect添加清理函数,移除对应监听器 - 用
useCallback包裹change函数,减少不必要的重复绑定
修改后的完整代码:
import { useEffect, useState, useCallback } from 'react'; export const useIsOnline = () => { const [online, setOnline] = useState(true); const checkOnline = useCallback(async () => { const url = new URL(window.location.origin); // 标记组件是否仍处于挂载状态 let isMounted = true; try { const response = await fetch(url); if (isMounted) { setOnline(response.ok); } } catch { if (isMounted) { setOnline(false); } } // 返回清理函数,组件卸载时切换标记状态 return () => { isMounted = false; }; }, []); const change = useCallback(() => { // 改用函数式更新,避免依赖online状态 setOnline(prev => !prev); }, []); useEffect(() => { const cleanupCheck = checkOnline(); return cleanupCheck; }, [checkOnline]); useEffect(() => { window.addEventListener('online', change); window.addEventListener('offline', change); // 组件卸载时移除事件监听 return () => { window.removeEventListener('online', change); window.removeEventListener('offline', change); }; }, [change]); return online; };
额外说明:
checkOnline中的isMounted标志位会在组件卸载时置为false,确保fetch完成后不会执行状态更新- 事件监听的清理函数能保证组件卸载后不再响应
online/offline事件 change函数用函数式更新后不再依赖online状态,配合useCallback让监听只绑定一次,避免重复绑定问题
内容的提问来源于stack exchange,提问作者seyan
相关产品推荐
相关产品推荐

