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

自定义useIsOnline Hook触发React内存泄漏错误,如何修复?

修复useIsOnline Hook的内存泄漏问题

你遇到的错误根源有两个:

  1. 异步fetch请求完成时,组件可能已经卸载,此时调用setOnline会触发已卸载组件的状态更新警告
  2. 给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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 13:35:24