React Router导航栏Link报错:useHref需在Router组件上下文内使用
解决React Router中
useHref() may be used only in the context of a <Router> component错误 问题场景
在React Router项目中,header.tsx里使用react-router-dom的Link组件跳转至Speaker页面时,触发以下错误:
Uncaught Error: useHref() may be used only in the context of a
component
相关代码如下:
index.tsx
const router = createBrowserRouter([ { path: "/", element: <Home />, errorElement: <ErrorPage />, }, { path: "about", element: <About />, }, { path: "speaker", element: <Speaker />, }, ]); ReactDOM.createRoot(document.getElementById('root')!).render( <React.StrictMode> <Header /> <RouterProvider router={router} /> </React.StrictMode> );
header.tsx
import AppBar from '@mui/material/AppBar'; import Box from '@mui/material/Box'; import Toolbar from '@mui/material/Toolbar'; import Typography from '@mui/material/Typography'; import Button from '@mui/material/Button'; import IconButton from '@mui/material/IconButton'; import MenuIcon from '@mui/icons-material/Menu'; import { Link } from 'react-router-dom'; export default function Header() { return ( <Box sx={{ flexGrow: 1 }}> <AppBar position="static"> <Toolbar> <IconButton size="large" edge="start" color="inherit" aria-label="menu" sx={{ mr: 2 }} > <MenuIcon /> </IconButton> <Typography variant="h6" component="div" sx={{ flexGrow: 1 }}> News </Typography> <Button color="inherit">Login</Button> <Link to="/speaker">Speaker</Link> </Toolbar> </AppBar> </Box> ); }
问题原因
Header组件被直接渲染在<RouterProvider>之外,导致Link组件无法访问React Router提供的路由上下文。Link内部依赖的useHref钩子必须在路由上下文(即<RouterProvider>或传统的<BrowserRouter>等路由组件内部)中才能正常工作。
解决方案
将Header组件移入路由上下文内部,推荐通过布局组件的方式实现全局导航栏,确保所有路由页面都能共享Header且处于路由上下文里。
步骤1:创建布局组件
新建Layout.tsx,包含Header和Outlet(用于渲染子路由内容):
import { Outlet } from 'react-router-dom'; import Header from './header'; export default function Layout() { return ( <> <Header /> <Outlet /> </> ); }
步骤2:修改路由配置
在index.tsx中,将根路由的element替换为<Layout />,并将原Home组件作为根路由的子路由:
const router = createBrowserRouter([ { path: "/", element: <Layout />, // 使用布局组件 errorElement: <ErrorPage />, children: [ { path: "/", element: <Home /> }, // 原首页作为子路由 { path: "about", element: <About /> }, { path: "speaker", element: <Speaker /> }, ], }, ]); ReactDOM.createRoot(document.getElementById('root')!).render( <React.StrictMode> <RouterProvider router={router} /> // 现在Header在路由上下文内部 </React.StrictMode> );
替代方案(快速调整)
如果不想创建单独的布局组件,也可以直接将Header移到根路由的element中:
const router = createBrowserRouter([ { path: "/", element: ( <> <Header /> <Outlet /> </> ), errorElement: <ErrorPage />, children: [ { path: "/", element: <Home /> }, { path: "about", element: <About /> }, { path: "speaker", element: <Speaker /> }, ], }, ]); // 渲染部分只保留RouterProvider ReactDOM.createRoot(document.getElementById('root')!).render( <React.StrictMode> <RouterProvider router={router} /> </React.StrictMode> );
验证效果
修改后,Header组件处于<RouterProvider>提供的路由上下文内部,Link组件可以正常调用useHref生成跳转路径,错误将被解决。
内容的提问来源于stack exchange,提问作者juiz
相关产品推荐
相关产品推荐

