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

React-router-dom多页面路由切换时,如何实现类似beforeunload的事件处理?

解决方案

React Router v5 实现方式

要拦截内部路由跳转,需正确使用history.block,它能监听所有通过react-router发起的页面切换(包括点击<Link>、浏览器前进/后退)。结合window.beforeunload可覆盖所有离开场景:

import { useHistory } from 'react-router-dom';
import { useEffect } from 'react';

function TargetPage() {
  const history = useHistory();

  useEffect(() => {
    // 拦截内部路由跳转
    const unblock = history.block((transition) => {
      const shouldLeave = window.confirm('确定要离开当前页面吗?');
      if (shouldLeave) {
        unblock(); // 解除拦截,允许后续跳转
        transition.retry(); // 执行本次路由切换
      }
      return false; // 默认阻止跳转
    });

    // 处理页面刷新、关闭、跨域跳转
    const handleBeforeUnload = (e) => {
      e.preventDefault();
      e.returnValue = ''; // 触发浏览器默认确认提示
    };
    window.addEventListener('beforeunload', handleBeforeUnload);

    // 组件卸载时清理监听
    return () => {
      unblock();
      window.removeEventListener('beforeunload', handleBeforeUnload);
    };
  }, [history]);

  return <div>当前页面内容</div>;
}

React Router v6 实现方式

v6移除了history.block,可通过useBlocker钩子或全局路由配置实现拦截:

1. 组件内局部拦截

import { useBlocker } from 'react-router-dom';
import { useEffect } from 'react';

function TargetPage() {
  // 拦截内部路由跳转
  const blocker = useBlocker((transition) => {
    if (window.confirm('确定要离开吗?')) {
      transition.proceed(); // 允许跳转
    }
  });

  // 处理页面卸载场景
  useEffect(() => {
    const handleBeforeUnload = (e) => {
      e.preventDefault();
      e.returnValue = '';
    };
    window.addEventListener('beforeunload', handleBeforeUnload);
    return () => window.removeEventListener('beforeunload', handleBeforeUnload);
  }, []);

  return <div>当前页面内容</div>;
}

2. 全局路由拦截

如果需要在所有页面生效,可在创建路由时配置全局blocker:

import { createBrowserRouter, RouterProvider } from 'react-router-dom';

const router = createBrowserRouter(
  [
    // 你的路由列表配置
    { path: '/', element: <HomePage /> },
    { path: '/detail', element: <TargetPage /> }
  ],
  {
    blocker: async ({ currentLocation, nextLocation }) => {
      return window.confirm('确定要离开当前页面吗?');
      // 返回true允许跳转,false阻止跳转
    }
  }
);

function App() {
  return <RouterProvider router={router} />;
}

关键注意点

  • 确保组件处于路由上下文内(被<BrowserRouter>v5或<RouterProvider>v6包裹),否则无法获取路由相关钩子。
  • 两种拦截逻辑搭配使用,才能覆盖内部路由切换和页面卸载所有场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 19:45:31