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

React:仅关闭标签页时触发后端退出请求,避免页面刷新触发

解决方案

要实现仅在关闭标签页时执行退出逻辑,需要解决两个核心问题:区分页面刷新与标签页关闭,以及确保异步请求在页面卸载时能正常完成。以下是具体实现方案:

核心思路

浏览器没有直接提供区分刷新和关闭标签页的API,我们可以通过监听页面可见性变化(visibilitychange)结合定时器来间接判断:

  • 刷新或切换标签页时,页面会先变为hidden,但很快会重新变为visible,此时可以取消退出操作;
  • 关闭标签页时,页面变为hidden后不会再恢复可见,定时器到期后执行退出逻辑。

同时,使用navigator.sendBeacon替代axios发送请求——这个API是浏览器专门为页面卸载时的异步请求设计的,能保证请求在后台完成,避免被浏览器中断。

代码实现

import { useEffect } from 'react';
import Cookies from 'js-cookie';

useEffect(() => {
  let logoutTimer;

  const handleVisibilityChange = () => {
    if (document.visibilityState === 'hidden') {
      // 页面隐藏时启动定时器,1秒后执行退出逻辑
      logoutTimer = setTimeout(() => {
        // 清除_token Cookie
        Cookies.remove('_token');
        // 发送logout请求
        navigator.sendBeacon('http://localhost:3001/logout');
      }, 1000);
    } else {
      // 页面恢复可见(刷新/切换标签返回),取消定时器
      clearTimeout(logoutTimer);
    }
  };

  document.addEventListener('visibilitychange', handleVisibilityChange);

  return () => {
    document.removeEventListener('visibilitychange', handleVisibilityChange);
    clearTimeout(logoutTimer);
  };
}, []);

关键说明

  1. 可见性监听逻辑:

    • 当用户切换标签页或刷新页面,页面会短暂变为hidden后恢复visible,此时定时器会被清除,不会执行退出操作;
    • 当用户关闭标签页,页面保持hidden状态,定时器到期后执行清除Cookie和发送logout请求。
  2. 请求方式替换:

    • 原代码中使用axios的异步请求在beforeunload事件中大概率会被浏览器中断,无法保证请求送达后端;
    • navigator.sendBeacon会将请求放入浏览器的后台任务队列,确保页面卸载前完成请求发送,且不会阻塞页面卸载流程。
  3. 定时器时长:

    • 设置1秒是为了给刷新/标签切换留足恢复可见的时间,你可以根据实际情况调整这个数值(建议500ms-2000ms之间)。

备选方案(基于导航类型判断)

如果你的目标浏览器支持PerformanceNavigationTiming API,也可以通过判断页面导航类型来区分刷新:

import { useEffect } from 'react';
import Cookies from 'js-cookie';

useEffect(() => {
  const handleBeforeUnload = () => {
    const navigationEntry = performance.getEntriesByType('navigation')[0];
    // 仅当导航类型不是刷新(reload)时执行退出逻辑
    if (navigationEntry?.type !== 'reload') {
      Cookies.remove('_token');
      navigator.sendBeacon('http://localhost:3001/logout');
    }
  };

  window.addEventListener('beforeunload', handleBeforeUnload);

  return () => {
    window.removeEventListener('beforeunload', handleBeforeUnload);
  };
}, []);

注意:这个方案无法区分“关闭标签页”和“导航到其他页面”,如果你的需求是仅关闭标签页时执行,优先选择第一种方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 07:55:00