如何在react-router-dom v6页面导航时处理beforeunload事件
React Router v6 客户端导航时触发状态保存逻辑
要在React Router v6的客户端导航(比如通过NavLink跳转)时执行状态保存API调用,你可以结合React Router的钩子和React的生命周期处理,同时保留原有的浏览器刷新/关闭处理逻辑,具体方案如下:
方案一:利用组件卸载的清理函数
当通过客户端路由离开当前页面组件时,组件会被卸载,此时可以通过useEffect的清理函数触发API调用:
import React from 'react'; const YourPageComponent = () => { // 假设这是需要保存的状态 const [pageState, setPageState] = React.useState({}); // 封装状态保存的API调用逻辑 const saveState = async () => { try { await fetch('/api/save-latest-state', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(pageState) }); console.log('状态已成功提交'); } catch (error) { console.error('提交状态失败:', error); } }; // 处理浏览器刷新/关闭的情况 React.useEffect(() => { const handleBeforeUnload = () => { saveState(); }; window.addEventListener('beforeunload', handleBeforeUnload); return () => window.removeEventListener('beforeunload', handleBeforeUnload); }, [pageState]); // 处理客户端导航离开当前页面的情况(组件卸载时执行) React.useEffect(() => { return () => { saveState(); }; }, [pageState]); // 页面组件的其他逻辑和渲染 return ( <div> {/* 页面内容 */} </div> ); }; export default YourPageComponent;
方案二:拦截导航动作(支持确认提示)
如果需要在用户导航离开前添加确认提示,可以使用useNavigate的unblock方法拦截导航:
import React from 'react'; import { useNavigate } from 'react-router-dom'; const YourPageComponent = () => { const [pageState, setPageState] = React.useState({}); const navigate = useNavigate(); const saveState = async () => { try { await fetch('/api/save-latest-state', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(pageState) }); console.log('状态已成功提交'); } catch (error) { console.error('提交状态失败:', error); } }; // 处理浏览器刷新/关闭 React.useEffect(() => { const handleBeforeUnload = () => { saveState(); }; window.addEventListener('beforeunload', handleBeforeUnload); return () => window.removeEventListener('beforeunload', handleBeforeUnload); }, [pageState]); // 拦截客户端导航 React.useEffect(() => { const unblockNavigation = navigate((location) => { // 可添加确认逻辑,比如: // const shouldLeave = window.confirm('确定要离开吗?未保存的内容会提交'); // if (!shouldLeave) return false; // 执行状态保存 saveState(); // 允许导航继续 return true; }); // 组件卸载时解除拦截 return () => unblockNavigation(); }, [navigate, pageState]); return ( <div> {/* 页面内容 */} </div> ); }; export default YourPageComponent;
关键说明
- 两个方案都将
pageState作为useEffect的依赖项,确保状态更新时,effect能获取到最新的状态值,避免闭包问题。 - 方案一适合无需用户确认、自动保存状态的场景;方案二适合需要拦截导航并提示用户的场景。
内容的提问来源于stack exchange,提问作者Utsav Patel
相关产品推荐
相关产品推荐

