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

React项目中navigator.block不是函数的路由拦截问题求助

React Router v6.3.0 导航拦截报错 navigator.block is not a function 解决方法

问题原因

react-router-dom v6.3.0 中,useNavigate 返回的导航器对象并没有内置 block 方法,这个导航拦截API是在v6.4.0版本之后才正式作为稳定功能推出的。你之前的自定义 useBlocker 尝试调用不存在的 navigator.block,自然会触发报错。

解决方案一:升级到 v6.4.0+ 使用官方稳定API

这是最推荐的方案,升级后可以直接使用官方提供的 useBlocker 和 usePrompt API,无需自己手动实现拦截逻辑。

  1. 升级依赖
npm install react-router-dom@^6.4.0
# 或者 yarn
yarn add react-router-dom@^6.4.0
  1. 替换自定义拦截逻辑
    直接使用官方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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 08:30:49