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
相关产品推荐
相关产品推荐

