React Router 6.4.3中createBrowserRouter报错:useNavigate需在Router上下文使用
问题现象
从 BrowserRouter 切换为 createBrowserRouter 后,出现以下错误:
useNavigate() may be used only in the context of a
component.
错误触发自 AuthProvider 组件,该组件内部调用了 useNavigate,但当前组件层级中 AuthProvider 位于 RouterProvider 之外,无法获取路由上下文。
核心原因
当前代码结构中,AuthProvider 在 index.tsx 里作为 App 的父组件渲染,而 RouterProvider 是在 App 内部渲染的。这导致 AuthProvider 初始化时,路由上下文还未被创建,useNavigate 无法拿到所需的路由实例。
解决方案
方案一:将 AuthProvider 整合到路由配置中(推荐)
把 AuthProvider 作为根路由的元素,让所有子路由都处于其包裹下,同时确保它在路由上下文范围内:
- 修改 App.tsx 的路由配置
const router = createBrowserRouter([ { element: <AuthProvider />, children: [ { element: <ProtectedRoute />, children: [ { path: '/', element: <DashboardLayout />, children: [ { index: true, element: <HomePage />, }, { path: 'about', element: <AboutPage />, }, ], }, ], }, { path: '/auth', element: <Auth />, }, ], }, ]); const App = () => { const { isLoading } = useAuth0(); if (isLoading) { return <LoaderPage />; } return ( <> <Box> <CssBaseline /> <RouterProvider router={router} /> </Box> </> ); };
- 调整 index.tsx 层级
移除index.tsx中的AuthProvider,由路由配置负责渲染:
const container = document.getElementById('root')!; const root = createRoot(container); root.render( <React.StrictMode> <Provider store={store}> <ThemeProvider theme={theme}> <App /> </ThemeProvider> </Provider> </React.StrictMode> );
方案二:将 RouterProvider 提到 index.tsx 外层
如果不想修改路由结构,可把 RouterProvider 移到 index.tsx 中,确保 AuthProvider 处于路由上下文内:
- 拆分路由配置到单独文件(如 router.tsx)
export const router = createBrowserRouter([ { element: <ProtectedRoute />, children: [ { path: '/', element: <DashboardLayout />, children: [ { index: true, element: <HomePage />, }, { path: 'about', element: <AboutPage />, }, ], }, ], }, { path: '/auth', element: <Auth />, }, ]);
- 修改 index.tsx
import { router } from './router'; const container = document.getElementById('root')!; const root = createRoot(container); root.render( <React.StrictMode> <Provider store={store}> <RouterProvider router={router}> <AuthProvider> <ThemeProvider theme={theme}> <App /> </ThemeProvider> </AuthProvider> </RouterProvider> </Provider> </React.StrictMode> );
- 简化 App.tsx
移除内部路由配置,直接用Outlet渲染路由内容:
const App = () => { const { isLoading } = useAuth0(); if (isLoading) { return <LoaderPage />; } return ( <> <Box> <CssBaseline /> <Outlet /> </Box> </> ); };
原理说明
useNavigate、useLocation 等 React Router Hooks 必须在 RouterProvider(或传统 BrowserRouter)提供的上下文环境中使用。调整组件层级后,AuthProvider 会在路由上下文初始化完成后渲染,此时调用 useNavigate 就能正常获取路由实例。
内容的提问来源于stack exchange,提问作者qweezz
相关产品推荐
相关产品推荐

