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

React 18与React-Router 6中如何在导航栏获取路由参数

如何在React Router v6的<Routes>外获取路由参数?

问题描述

我有一个React前端项目,需要在<Routes>组件之外的导航菜单(NavMenu类组件)中获取路由参数auxParam,但无法直接使用useParams()。尝试将<Routes>移到<NavMenu>之外时出现报错:

Error: [default] is not a component. All component children of must be a or <React.Fragment>

React 18之前我用this.props.location.pathname.split...的临时方案,但不够可靠。同时react-router-dom@6已经移除了withRouter高阶组件。

简化后的项目代码如下:

index.tsx

ReactDOM.createRoot(document.getElementById('react-hook'))
    .render(
        <Provider store={store}>
            <BrowserRouter>
                <App />
            </BrowserRouter>
        </Provider>
    );

app.tsx

export default () => (
    <Layout>
        <Routes>
            <Route path='/:auxParam/site/foo/:startIndex?' Component={Extra} />
        </Routes>
    </Layout>
);

layout.tsx

export default (props: { children?: React.ReactNode }) => (
    <React.Fragment>
        <NavMenu />
        <Container tag="main">
            {props.children}
        </Container>
    </React.Fragment>
);
class NavMenu extends React.PureComponent<NavMenuProps, { isOpen: boolean }> {
  public render() {
    const auxParam: string = ...?...; // 如何获取这个参数?
    return (
      <header>
        <Navbar>
          <Container>
            <NavbarBrand tag={Link} to="/">My site (React)</NavbarBrand>
            <ul>
              <NavItem>
                <NavLink tag={Link} to={`/${aux}/site/foo`}>Extra</NavLink>
              </NavItem>
            </ul>
          </Container>
        </Navbar>
      </header>
    );
  }
}
export default NavMenu;

解决方案

1. 自定义withRouter高阶组件

React Router v6官方移除了withRouter,但可以自行封装,让类组件能访问路由相关hooks:

import { useLocation, useNavigate, useParams, useMatch } from 'react-router-dom';

const withRouter = (Component: React.ComponentType) => {
  const Wrapper = (props: any) => {
    const location = useLocation();
    const navigate = useNavigate();
    const params = useParams();
    const match = useMatch('/:auxParam/site/foo/:startIndex?'); // 匹配目标路由规则

    return <Component {...props} location={location} navigate={navigate} params={params} match={match} />;
  };

  return Wrapper;
};

在NavMenu中使用:

class NavMenu extends React.PureComponent<NavMenuProps & { params: { auxParam?: string } }, { isOpen: boolean }> {
  public render() {
    const { auxParam } = this.props.params;
    return (
      // ... 原有导航代码,直接使用auxParam
    );
  }
}

export default withRouter(NavMenu);

2. 转为函数组件,直接使用useParams

如果允许修改NavMenu为函数组件,直接使用React Router的hooks更简洁:

import { useParams } from 'react-router-dom';
import { useState } from 'react';

const NavMenu = () => {
  const { auxParam } = useParams<{ auxParam: string }>();
  const [isOpen, setIsOpen] = useState(false);

  return (
    <header>
      <Navbar>
        <Container>
          <NavbarBrand tag={Link} to="/">My site (React)</NavbarBrand>
          <ul>
            <NavItem>
              <NavLink tag={Link} to={`/${auxParam}/site/foo`}>Extra</NavLink>
            </NavItem>
          </ul>
        </Container>
      </Navbar>
    </header>
  );
};

export default NavMenu;

3. 使用useMatch精准匹配路由(支持函数/类组件)

如果路由结构复杂,useMatch可以精准匹配指定路由并提取参数:

  • 函数组件直接使用:
import { useMatch } from 'react-router-dom';

const NavMenu = () => {
  const match = useMatch('/:auxParam/site/foo/:startIndex?');
  const auxParam = match?.params.auxParam || '';

  return (
    // ... 使用auxParam渲染导航
  );
};
  • 类组件可通过自定义withRouter将match传入,参考方案1。

4. 通过路由上下文解析(不推荐,内部API可能变更)

React Router v6提供了内部上下文RouterContext,可直接消费获取路由信息,但注意这是未公开的API,未来可能变动:

import { RouterContext } from 'react-router-dom';

class NavMenu extends React.PureComponent<NavMenuProps, { isOpen: boolean }> {
  static contextType = RouterContext;
  context!: React.ContextType<typeof RouterContext>;

  public render() {
    const { location } = this.context;
    // 用正则从pathname中提取参数,比split更可靠
    const paramMatch = location.pathname.match(/^\/([^/]+)\/site\/foo/);
    const auxParam = paramMatch ? paramMatch[1] : '';

    return (
      // ... 使用auxParam渲染导航
    );
  }
}

export default NavMenu;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 14:15:13