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

React Router V6中如何正确设置父级NavLink激活状态

多层级导航中NavLink激活状态异常的解决方法

场景与路由配置

我搭建了一个多层级导航,结构如下:

Home     Companies     

Company Details     Users

对应的React Router路由配置:

<Routes>
  <Route index element={<Home />} />
  <Route path="companies" element={<Companies />}>
    <Route index element={<CompaniesList />} />
    <Route path=":companyId" element={<Company />}>
      <Route index element={<CompanyDetail />} />
      <Route path="users" element={<Users />}>
        <Route index element={<UserList />} />
        <Route path=":userId" element={<UserDetail />} />
      </Route>
    </Route>
  </Route>
</Routes>

实际路由层级:

Companies:            /companies
  - Details:          /companies/:companyId
  - Users:            /companies/:companyId/users
      - User Details: /companies/:companyId/users/:userId

当前问题

我用<NavLink>给导航项设置激活类:

<NavLink to="..." className={({ isActive }) => (isActive ? 'is-active' : '')} />
  • 进入Details页面时,Details和Companies导航项正常激活;
  • 进入Users页面(/companies/:companyId/users)时,Companies、Details、Users三个都被激活,不希望Details激活;
  • 给Details的<NavLink>加end属性后,Details不再错误激活,但Companies导航项也失去激活状态;进入User Details页面时,所有导航项都不激活;
  • 尝试用useLocation()判断路径包含关系,因为/companies/:companyId/users包含/companies/:companyId,还是会错误匹配到Details。

需求

需要准确判断路由的真正父级关系:Companies是Users的父级,但Details不是。


解决方案

方法1:用useMatch精确匹配路由路径

React Router的useMatch钩子可以精确匹配路由规则,不会因为路径包含就误判。

  • 对于Details导航项,只在路径完全匹配/companies/:companyId时激活:
import { useMatch } from 'react-router-dom';

// 在导航组件中
const isDetailActive = useMatch('/companies/:companyId');

<NavLink 
  to={`/companies/${companyId}`}
  className={isDetailActive ? 'is-active' : ''}
>
  Company Details
</NavLink>
  • 对于Companies导航项,匹配所有/companies开头的路由(包括子路由):
const isCompaniesActive = useMatch('/companies/*') || useMatch('/companies');

<NavLink 
  to="/companies"
  className={isCompaniesActive ? 'is-active' : ''}
>
  Companies
</NavLink>

方法2:自定义正则匹配逻辑

用正则表达式精确匹配Details的路径,确保只有当路径是/companies/xxx(没有后续子路径)时才激活:

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

const location = useLocation();
// 匹配 /companies/任意字符,但后面不能有斜杠(即没有子路径)
const detailPathRegex = /^\/companies\/[^\/]+$/;
const isDetailActive = detailPathRegex.test(location.pathname);

<NavLink 
  to={`/companies/${companyId}`}
  className={isDetailActive ? 'is-active' : ''}
>
  Company Details
</NavLink>

方法3:基于路径层级判断

拆分当前路径的层级,Details的路径层级是2(companies/xxx),Users及子路由的层级是3+,以此区分:

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

const location = useLocation();
// 拆分路径并过滤空字符串,得到路径段数组
const pathSegments = location.pathname.split('/').filter(Boolean);

// 只有路径段长度为2,且第一段是companies时,才激活Details
const isDetailActive = pathSegments.length === 2 && pathSegments[0] === 'companies';

以上方法都能解决你的问题,推荐优先使用useMatch,它是React Router提供的原生方案,更贴合路由逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 18:24:41