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

React中beforeunload事件关闭标签页/浏览器时无法发送请求的解决方案咨询

React中beforeunload事件关闭标签页/浏览器时无法发送请求的解决方案咨询

我完全理解你的需求:在用户离开React页面(不管是点击导航跳转、刷新页面、回退还是直接关闭标签/浏览器)时,都要给服务器发请求标记当前用户不再操作这个页面。你现在的代码在刷新、跳转、回退场景下能正常触发请求,但关闭标签或浏览器时就失效了,而且加了e.preventDefault()反而搞坏了原本正常的请求逻辑,对吧?

问题根源

你当前用的async/await搭配fetch属于异步请求,当浏览器触发beforeunload准备关闭页面时,它不会等待异步请求完成就会终止页面进程,所以这种场景下请求根本来不及发送出去。而e.preventDefault()会触发浏览器默认的“确认离开”弹窗,同时干扰事件的正常执行流程,导致原本能触发的请求也失效,这显然不是你想要的结果。

解决方案:使用navigator.sendBeacon()

这是浏览器专门为“页面卸载时发送数据”的场景设计的API,它的核心优势是浏览器会在后台异步发送请求,并且会确保请求完成后再关闭页面,不会像普通fetch那样被直接终止。

修改你的代码如下:

window.addEventListener('beforeunload', function (e) {
  // 构造需要发送的JSON数据,转成Blob格式以指定Content-Type
  const requestBody = JSON.stringify({}); // 可根据需求添加请求体内容
  const blob = new Blob([requestBody], { type: 'application/json' });
  
  // 发送请求
  navigator.sendBeacon('/connetion', blob);
  
  // 如果只是简单的无请求体请求,也可以直接写:
  // navigator.sendBeacon('/connetion');
});

关键注意事项

  • sendBeacon默认是POST请求,如果需要发送JSON格式数据,必须用Blob包装,否则请求的Content-Type会是text/plain,服务器可能无法正确解析。
  • 绝对不要在这个事件里加e.preventDefault(),除非你明确需要弹出“确定要离开吗?”的确认框,这个操作会严重干扰请求的正常发送逻辑。
  • 测试关闭标签页场景时,注意部分浏览器(比如Chrome)在开发者工具打开的情况下,会延迟页面卸载方便调试,生产环境下是正常工作的。

React组件内的最佳实践

如果你是在React组件中使用这个事件,建议在useEffect中添加监听,并在组件卸载时移除监听,避免内存泄漏:

import { useEffect } from 'react';

function YourFormPage() {
  useEffect(() => {
    const handlePageUnload = (e) => {
      const requestBody = JSON.stringify({});
      const blob = new Blob([requestBody], { type: 'application/json' });
      navigator.sendBeacon('/connetion', blob);
    };

    window.addEventListener('beforeunload', handlePageUnload);

    // 组件卸载时移除监听
    return () => {
      window.removeEventListener('beforeunload', handlePageUnload);
    };
  }, []);

  // 其他组件逻辑...
  return <div>你的表单页面内容</div>;
}

这样修改后,不管用户通过哪种方式离开页面,请求都能稳定发送到服务器了。

备注:内容来源于stack exchange,提问作者ayush jain

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 16:29:49