react-router-dom v6未导出useBlocker、usePrompt,如何实现页面离开提醒功能
React Router v6 实现页面离开提醒方案
方案1:v6.4+ 数据路由(Data Router)直接使用官方恢复的API
React Router 从v6.4版本开始,在createBrowserRouter/createHashRouter等数据路由模式下重新恢复了usePrompt和useBlocker两个API,可直接使用:
基础用法(usePrompt)
适合直接用浏览器默认提示框的场景:
import { usePrompt } from 'react-router-dom'; function EditPage() { // 第一个参数为提示文案,第二个参数为是否触发拦截的判断条件 usePrompt( "你当前有未保存的修改,确定要离开吗?", true // 可替换为实际业务判断,比如表单是否被修改、是否有未提交内容等 ); return <div>编辑页面内容</div> }
自定义弹框用法(useBlocker)
适合需要自定义拦截弹窗样式的场景:
import { useBlocker } from 'react-router-dom'; function EditPage() { // 传入拦截判断逻辑,返回true则触发拦截 const blocker = useBlocker( ({ currentLocation, nextLocation }) => currentLocation.pathname !== nextLocation.pathname && true // 替换为实际业务判断 ); // 拦截触发时渲染自定义弹窗 if (blocker.state === "blocked") { return ( <div className="confirm-modal"> <p>你有未保存的修改,确定离开当前页面吗?</p> <button onClick={() => blocker.proceed()}>确定离开</button> <button onClick={() => blocker.reset()}>留在页面</button> </div> ) } return <div>编辑页面内容</div> }
方案2:非数据路由/低于v6.4版本自定义实现
如果你使用的是传统<BrowserRouter>组件式路由,或者v6.4以下的版本,可以自定义Hook实现同等效果:
import { useEffect, useCallback, useContext, useState } from 'react'; import { UNSAFE_NavigationContext as NavigationContext } from 'react-router-dom'; // 自定义页面离开拦截Hook function useCustomPrompt(shouldBlock, tipMessage) { const { navigator } = useContext(NavigationContext); // 拦截浏览器刷新、关闭页面的场景 const handleBeforeUnload = useCallback((e) => { if (!shouldBlock) return; e.preventDefault(); e.returnValue = tipMessage; return tipMessage; }, [shouldBlock, tipMessage]); useEffect(() => { if (!shouldBlock) return; // 拦截React Router内部路由跳转的场景 const unblock = navigator.block((transition) => { const confirmLeave = window.confirm(tipMessage); if (confirmLeave) { unblock(); transition.retry(); } }); window.addEventListener('beforeunload', handleBeforeUnload); return () => { unblock(); window.removeEventListener('beforeunload', handleBeforeUnload); }; }, [shouldBlock, tipMessage, navigator, handleBeforeUnload]); } // 组件内使用示例 function EditPage() { // 示例:判断表单是否有未保存的修改 const [formDirty, setFormDirty] = useState(false); // 调用自定义Hook传入拦截条件和提示文案 useCustomPrompt(formDirty, "你有未保存的修改,确定离开吗?"); return <div>编辑页面内容</div> }
注意:自定义实现依赖的
UNSAFE_NavigationContext虽然标了不安全标识,但属于React Router内部稳定使用的API,兼容性较好,同时覆盖了路由跳转、浏览器前进后退、刷新/关闭页面的所有拦截场景。
内容的提问来源于stack exchange,提问作者Nguyễn Tuấn Kiệt
相关产品推荐
相关产品推荐

