如何判断React Router中路由或其子路由是否处于激活状态?
解决方案
方案一:复用NavLink的激活判断逻辑
NavLink本身已经内置了完整的激活判断(包括匹配子路由的情况),直接通过它的onChange事件获取激活状态即可,无需自己编写匹配逻辑:
import { ExpandMore } from '@mui/icons-material'; import { ButtonBase, IconButton } from '@mui/material'; import cx from 'classnames'; import { NavLink, To } from 'react-router-dom'; import { useState } from 'react'; interface NavButtonProps { name: string; to: To; } export function NavButton(props: NavButtonProps) { const [isActive, setIsActive] = useState(false); return ( <ButtonBase component="div" className={cx({ active: isActive })}> <NavLink to={props.to} onChange={({ isActive: navLinkActive }) => setIsActive(navLinkActive)} > {props.name} </NavLink> <IconButton onClick={openMenuWithLinksToNestedRoutes}> <ExpandMore /> </IconButton> </ButtonBase> ); }
这个方案最简便,完全复用React Router内置的激活规则,和NavLink自身的激活逻辑保持一致,不需要手动处理路径匹配。
方案二:使用useMatch匹配父路由及子路由
如果想通过useMatch实现,可以构造包含子路由的匹配模式,同时处理原路径本身的匹配:
import { ExpandMore } from '@mui/icons-material'; import { ButtonBase, IconButton } from '@mui/material'; import cx from 'classnames'; import { NavLink, To, useMatch, useResolvedPath } from 'react-router-dom'; interface NavButtonProps { name: string; to: To; } export function NavButton(props: NavButtonProps) { // 解析传入的路径,处理相对路径情况 const resolvedPath = useResolvedPath(props.to); // 构造匹配模式:匹配当前路径及所有子路由 const parentPattern = `${resolvedPath.pathname}/*`; // 同时匹配原路径和子路由路径 const match = useMatch(resolvedPath.pathname) || useMatch(parentPattern); const active = Boolean(match); return ( <ButtonBase component="div" className={cx({ active })}> <NavLink to={props.to}> {props.name} </NavLink> <IconButton onClick={openMenuWithLinksToNestedRoutes}> <ExpandMore /> </IconButton> </ButtonBase> ); }
useResolvedPath用于将相对路径转为绝对路径,确保匹配逻辑在任何路由层级都生效。${path}/*模式会匹配该路径下的所有子路由,比如/admin/*会匹配/admin/users、/admin/users/123等。
关键说明
两种方案都能实现需求:当访问子路由时,父级的NavButton会被标记为激活状态。方案一更推荐,因为它直接复用了React Router经过验证的激活逻辑,避免自己编写匹配规则可能出现的错误。
内容的提问来源于stack exchange,提问作者Denis
相关产品推荐
相关产品推荐

