例如,有以下路由:
<Routes>
<Route path="admin">
<Route path="users">
<Route index element={<UserList />} />
<Route path="create" element={<UserDetails />} />
<Route path=":id" element={<UserDetails readOnly />} />
<Route path=":id/edit" element={<UserDetails />} />
</Route>
<Route path="roles">
<Route index element={<RoleList />} />
<Route path="create" element={<RoleDetails />} />
<Route path=":id" element={<RoleDetails readOnly />} />
<Route path=":id/edit" element={<RoleDetails />} />
</Route>
</Route>
<Route path="about" />
</Routes>
如果当前路由为/admin/users/123
,则/admin
和/admin/users
链路处于活动状态.它工作得很好.但我需要手动确定链接是否处于活动状态:
import { ExpandMore } from '@mui/icons-material';
import { ButtonBase, IconButton } from '@mui/material';
import cx from 'classnames';
import { NavLink, To, useMatch } from 'react-router-dom';
interface NavButtonProps {
name: string;
to: To;
}
export function NavButton(props: NavButtonProps) {
const match = useMatch(props.to as string); // What pattern to use here?
const active = Boolean(match);
return (
<ButtonBase component="div" className={cx({ active })}>
<NavLink to={props.to}>
{props.name}
</NavLink>
<IconButton onClick={openMenuWithLinksToNestedRoutes}>
<ExpandMore />
</IconButton>
</ButtonBase>
);
}
怎么做呢?我应该使用什么图案?我肯定能看到NavLink
个组件的源代码:
export const NavLink = React.forwardRef<HTMLAnchorElement, NavLinkProps>(
function NavLinkWithRef(
{
"aria-current": ariaCurrentProp = "page",
caseSensitive = false,
className: classNameProp = "",
end = false,
style: styleProp,
to,
children,
...rest
},
ref
) {
let path = useResolvedPath(to, { relative: rest.relative });
let location = useLocation();
let routerState = React.useContext(DataRouterStateContext);
let { navigator } = React.useContext(NavigationContext);
let toPathname = navigator.encodeLocation
? navigator.encodeLocation(path).pathname
: path.pathname;
let locationPathname = location.pathname;
let nextLocationPathname =
routerState && routerState.navigation && routerState.navigation.location
? routerState.navigation.location.pathname
: null;
if (!caseSensitive) {
locationPathname = locationPathname.toLowerCase();
nextLocationPathname = nextLocationPathname
? nextLocationPathname.toLowerCase()
: null;
toPathname = toPathname.toLowerCase();
}
let isActive =
locationPathname === toPathname ||
(!end &&
locationPathname.startsWith(toPathname) &&
locationPathname.charAt(toPathname.length) === "/");
但这真的很复杂.我认为应该有一种更简单的方法.