React项目中navigator.block不是函数的路由拦截问题求助
问题原因
react-router-dom v6.3.0 中,useNavigate 返回的导航器对象并没有内置 block 方法,这个导航拦截API是在v6.4.0版本之后才正式作为稳定功能推出的。你之前的自定义 useBlocker 尝试调用不存在的 navigator.block,自然会触发报错。
解决方案一:升级到 v6.4.0+ 使用官方稳定API
这是最推荐的方案,升级后可以直接使用官方提供的 useBlocker 和 usePrompt API,无需自己手动实现拦截逻辑。
- 升级依赖
npm install react-router-dom@^6.4.0 # 或者 yarn yarn add react-router-dom@^6.4.0
- 替换自定义拦截逻辑
直接使用官方API替代你现有的useBlocker.js和useCallbackPrompt.js:
使用 usePrompt 快速实现基础弹窗
import { usePrompt } from 'react-router-dom'; function YourFormComponent() { // 根据输入字段状态判断是否有未保存修改 const hasUnsavedChanges = /* 你的状态判断逻辑 */; // 触发默认确认弹窗 usePrompt({ message: '你有未保存的修改,确定要离开当前页面吗?', when: hasUnsavedChanges }); return ( {/* 你的表单内容 */} ); }
使用 useBlocker 自定义模态框
如果需要自定义弹窗样式(而不是默认的浏览器确认框),可以用 useBlocker 手动控制流程:
import { useBlocker } from 'react-router-dom'; import { useState, useEffect } from 'react'; import YourCustomModal from './YourCustomModal'; function YourFormComponent() { const hasUnsavedChanges = /* 你的状态判断逻辑 */; const blocker = useBlocker(hasUnsavedChanges); const [showModal, setShowModal] = useState(false); useEffect(() => { // 当导航被拦截时,显示自定义模态框 if (blocker.state === 'blocked') { setShowModal(true); } }, [blocker]); const handleConfirmLeave = () => { setShowModal(false); // 允许继续导航 blocker.proceed(); }; const handleCancelLeave = () => { setShowModal(false); // 取消导航,留在当前页面 blocker.reset(); }; return ( <> {/* 你的表单内容 */} {showModal && ( <YourCustomModal message="你有未保存的修改,确定要离开吗?" onConfirm={handleConfirmLeave} onCancel={handleCancelLeave} /> )} </> ); }
解决方案二:不升级版本,使用实验性API
如果暂时无法升级依赖,可以使用v6.3.0内置的实验性API unstable_useBlocker(注意:实验性API可能在后续版本被修改或移除)。
修改 useBlocker.js
import { unstable_useBlocker as useBlocker } from 'react-router-dom'; import { useEffect } from 'react'; export default function useCustomBlocker(shouldBlock) { const blocker = useBlocker(shouldBlock); useEffect(() => { if (blocker.state === 'blocked') { // 这里可以接入你的自定义弹窗逻辑 // 示例:用浏览器默认确认框 if (confirm('你有未保存的修改,确定要离开吗?')) { blocker.proceed(); } else { blocker.reset(); } } }, [blocker]); return blocker; }
修改 useCallbackPrompt.js
import { useState, useEffect } from 'react'; import useCustomBlocker from './useBlocker'; export default function useCallbackPrompt(when, callback) { const blocker = useCustomBlocker(when); const [showPrompt, setShowPrompt] = useState(false); useEffect(() => { if (blocker.state === 'blocked') { setShowPrompt(true); } }, [blocker]); const handleConfirm = () => { setShowPrompt(false); blocker.proceed(); // 执行自定义回调 if (typeof callback === 'function') { callback(); } }; const handleCancel = () => { setShowPrompt(false); blocker.reset(); }; return { showPrompt, handleConfirm, handleCancel }; }
使用时,在你的表单组件中调用 useCallbackPrompt 即可:
import useCallbackPrompt from './useCallbackPrompt'; import YourCustomModal from './YourCustomModal'; function YourFormComponent() { const hasUnsavedChanges = /* 你的状态判断逻辑 */; const { showPrompt, handleConfirm, handleCancel } = useCallbackPrompt(hasUnsavedChanges); return ( <> {/* 你的表单内容 */} {showPrompt && ( <YourCustomModal message="你有未保存的修改,确定要离开吗?" onConfirm={handleConfirm} onCancel={handleCancel} /> )} </> ); }
内容的提问来源于stack exchange,提问作者Prakash Patil
相关产品推荐
相关产品推荐

