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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 10:40:30