React Router v6用useMatch/useResolvedPath实现非精确路由匹配
问题根源
你当前自定义组件中useMatch配置了end: true,开启了完全精确匹配模式,只有访问路径和链接路径完全一致时才会判定为匹配,因此访问子路由时父级侧边栏链接无法触发激活状态。
修复方案
方案1:直接使用内置NavLink组件(推荐)
react-router-dom v6 提供的NavLink组件原生支持激活类名自动添加,且内置了路径边界判断逻辑,不会出现类似/teams误匹配/teamsnew路径的问题,不需要自己手写匹配规则:
import { NavLink } from 'react-router-dom'; interface SideMenuItemProps { icon : React.ReactNode; label: string; url: string; tooltip?: boolean; } export function SideMenuItem(props: SideMenuItemProps) { return( <li className={styles.item}> <Tooltip disabled={!props.tooltip} label={props.label} > <NavLink to={props.url} end={false} // 关闭精确匹配,只要当前路径是当前链接路径的子路径就判定激活 className={({ isActive }) => `${styles.link} ${isActive ? styles.active : ''}`} > {props.icon} </NavLink> </Tooltip> </li> ) }
如果后续需要在子页面中使用精确匹配的链接,只需要把对应组件的end属性设为true即可。
方案2:修正自定义匹配逻辑
如果你需要保留原有自定义匹配的写法,可以手动实现前缀匹配+路径边界判断,避免误匹配:
import { useLocation, useResolvedPath } from 'react-router-dom'; interface SideMenuItemProps { icon : React.ReactNode; label: string; url: string; tooltip?: boolean; end?: boolean; } export function SideMenuItem(props: SideMenuItemProps) { const resolved = useResolvedPath(props.url); const location = useLocation(); // 基础精确匹配 let isActive = location.pathname === resolved.pathname; // 非精确匹配模式下,判断当前路径是否为链接路径的子路径 if (!props.end) { isActive = isActive || location.pathname.startsWith(`${resolved.pathname}/`); } return( <li className={styles.item}> <Tooltip disabled={!props.tooltip} label={props.label} > <Link to={props.url} className={`${styles.link} ${isActive ? styles.active : ''} `}> {props.icon} </Link> </Tooltip> </li> ) }
侧边栏一级菜单调用时传入end={false}即可实现子路由自动激活父链接的效果。
匹配效果验证
修改后可以完全符合你的预期规则:
- 访问
/teams/name-of-team/squads:路径属于/teams的子路径,/teams链接自动激活 - 访问
/users/teams/234:路径属于/users的子路径,/users链接自动激活,不会误匹配/teams - 访问
/settings/security:路径属于/settings的子路径,/settings链接自动激活
内容的提问来源于stack exchange,提问作者Pedrohhcunha
相关产品推荐
相关产品推荐

