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

使用useNavigate()的replace:true时Safari未触发beforeunload问题

解决Safari中react-router-dom replace导航后后退失效的问题

问题根源

Safari对浏览器历史栈的replaceState实现逻辑和Chrome/Firefox存在差异:即使调用navigate("/home/room", { replace: true }),它仍可能保留/home/的历史记录,导致点击后退时直接返回主页而非触发页面卸载。

解决方案

通过手动拦截后退事件(popstate)并管理历史栈,强制实现预期逻辑:

代码实现

在/home/room对应的组件中添加以下逻辑:

import { useEffect } from 'react';

function RoomPage() {
  useEffect(() => {
    // 处理页面卸载确认
    const handleUnload = (e) => {
      e.preventDefault();
      e.returnValue = '';
      return '';
    };

    // 拦截浏览器后退事件
    const handlePopState = (e) => {
      // 判断是否是从当前页面后退到/home/
      if (window.location.pathname === '/home/') {
        e.preventDefault();
        
        // 手动弹出离开确认框(Safari对beforeunload提示限制较多,此方式更可靠)
        const isConfirmLeave = window.confirm('确定要离开当前房间吗?');
        
        if (isConfirmLeave) {
          // 清理历史栈并触发页面卸载
          window.history.go(-(window.history.length - 1));
          window.location.reload();
        } else {
          // 用户取消离开,恢复当前页面的历史记录
          window.history.pushState(null, '', '/home/room');
        }
      }
    };

    // 绑定事件监听
    window.addEventListener('beforeunload', handleUnload);
    window.addEventListener('popstate', handlePopState);

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

  return <div>房间页面</div>;
}

export default RoomPage;

关键逻辑说明

  1. 拦截后退动作:通过popstate事件监听浏览器后退,当检测到要返回/home/时,阻止默认路由跳转。
  2. 手动确认提示:由于Safari对beforeunload的自定义提示有严格限制,改用window.confirm确保用户能看到离开确认。
  3. 清理历史栈:用户确认离开后,通过window.history.go移除所有多余历史记录,再刷新页面触发卸载流程;取消则重新添加当前页面的历史记录,保持停留在房间页面。

额外注意点

  • 确保用户进入房间页面时有交互操作(比如点击进入按钮),Safari要求beforeunload事件必须由用户交互触发才能生效。
  • 若不需要刷新页面,也可以用window.close()(仅适用于通过window.open打开的弹窗)或跳转到外部链接来触发卸载。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 13:52:08