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

改用createBrowserRouter后useNavigate报错,需兼容useBlocker与全局模态框

解决方法

方案一:将GlobalModalProvider移入RouterProvider内部

这是最直接的处理方式,让模态框组件完全处于Router上下文范围内:

  1. 修改App.tsx的结构,把GlobalModalProvider从RouterProvider外层移到内层:
// App.tsx
import { RouterProvider } from 'react-router-dom';
import { router } from './router'; // 你用createBrowserRouter创建的路由实例
import GlobalModalProvider from './GlobalModalProvider';

function App() {
  return (
    <RouterProvider router={router}>
      <GlobalModalProvider>
        {/* 你的根路由组件,比如Root */}
      </GlobalModalProvider>
    </RouterProvider>
  );
}

export default App;
  1. 确保根路由组件(如Root)包含路由出口<Outlet />,这样模态框可以在任意路由页面触发,同时useNavigate能正常获取Router上下文。
  2. useBlocker的使用保持不变,直接在路由组件内调用即可,它本就处于Router上下文环境中。

方案二:传递navigate实例给GlobalModalProvider

如果无法移动ModalProvider的位置,可以手动传递navigate实例:

  1. 在Router内部的根组件中获取navigate,通过自定义Context传递给GlobalModalProvider:
// Root.tsx(根路由组件)
import { useNavigate } from 'react-router-dom';
import { createContext, useContext } from 'react';

const GlobalModalContext = createContext<{ navigate?: ReturnType<typeof useNavigate> }>({});

function Root() {
  const navigate = useNavigate();
  
  return (
    <GlobalModalContext.Provider value={{ navigate }}>
      <Outlet />
    </GlobalModalContext.Provider>
  );
}
  1. 修改GlobalModalProvider和模态框组件,使用传入的navigate代替useNavigate:
// GlobalModalProvider.tsx
import { GlobalModalContext } from './Root';

export function GlobalModalProvider({ children }: { children: React.ReactNode }) {
  return (
    <>
      {children}
      <SettingLogout />
    </>
  );
}

// SettingLogout组件
export function SettingLogout() {
  const { navigate } = useContext(GlobalModalContext);
  
  const handleLogout = () => {
    navigate?.('/login');
  };
  
  return <button onClick={handleLogout}>退出登录</button>;
}

方案三:使用unstable_HistoryRouter共享history对象

若需要ModalProvider保持在最外层,同时让useBlocker和useNavigate正常工作,可使用实验性的unstable_HistoryRouter(注意该API不稳定,生产环境需谨慎):

  1. 安装history包:
npm install history
  1. 创建history实例,用HistoryRouter包裹GlobalModalProvider和RouterProvider:
// App.tsx
import { unstable_HistoryRouter as HistoryRouter } from 'react-router-dom';
import { createBrowserHistory } from 'history';
import GlobalModalProvider from './GlobalModalProvider';
import { router } from './router';

const history = createBrowserHistory();

function App() {
  return (
    <HistoryRouter history={history}>
      <GlobalModalProvider>
        <RouterProvider router={router} />
      </GlobalModalProvider>
    </HistoryRouter>
  );
}

export default App;
  1. 此时模态框处于HistoryRouter上下文内,useNavigate和useBlocker都能基于共享的history实例正常工作。

内容的提问来源于stack exchange,提问作者jungmin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 00:22:01