例如,有以下路由:

<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) === "/");

但这真的很复杂.我认为应该有一种更简单的方法.

推荐答案

您可以让NavLink继续执行知道它何时处于活动状态的工作,并在处于活动状态时"泄漏"到外部组件作用域.NavLink有一个children渲染功能props ,可以传递给isActive个props .以下使用Reaction Ref的方法可能会满足您的需要.

export function NavButton(props: NavButtonProps) {
  const isActiveRef = React.useRef(false);

  return (
    <ButtonBase
      component="div"
      className={cx({ active: isActiveRef.current })}
    >
      <NavLink to={props.to}>
        {({ isActive }) => {
          isActiveRef.current = isActive;
          return props.name;
        }}
      </NavLink>
      <IconButton onClick={openMenuWithLinksToNestedRoutes}>
        <ExpandMore />
      </IconButton>
    </ButtonBase>
  );
}

另一种方法是在NavButton中使用本地状态,并创建一个可以通过useEffect挂钩传递isActive状态的"子"组件.

const Label = ({ setActive, isActive, name }) => {
  useEffect(() => {
    setActive(isActive);
  }, [isActive, setActive]);

  return name;
};

export function NavButton(props: NavButtonProps) {
  const [active, setActive] = React.useState(false);

  return (
    <ButtonBase component="div" className={cx({ active })}>
      <NavLink to={props.to}>
        {({ isActive }) => (
          <Label
            name={props.name}
            isActive={isActive}
            setActive={setActive}
          />
        )}
      </NavLink>
      <IconButton onClick={openMenuWithLinksToNestedRoutes}>
        <ExpandMore />
      </IconButton>
    </ButtonBase>
  );
}

Typescript相关问答推荐

如何在不使用变量的情况下静态判断运算式的类型?

TS 2339:属性切片不存在于类型DeliverableSignal产品[]上>'

在这种情况下,如何获得类型安全函数的返回值?

typescribe不能使用值来索引对象类型,该对象类型满足具有该值的另一个类型'

contextPaneTitleText类型的参数不能分配给remoteconfig类型的关键参数'""'''

根据上一个参数值查找参数类型,也返回类型

为什么有条件渲染会导致material 自动完成中出现奇怪的动画?

是否可以从函数类型中创建简化的类型,go 掉参数中任何看起来像回调的内容,而保留其余的内容?

嵌套对象的类型

在Typescript 中,有没有`index=unfined的速记?未定义:某个数组[索引]`?

推断从其他类型派生的类型

按函数名的类型安全类型脚本方法包装帮助器

如何将TS泛型用于react-hook-form接口?

在抽象类属性定义中扩展泛型类型

如何使用TypeScrip在EXPO路由链路组件中使用动态路由?

Rxjs将省略的可观测对象合并到一个数组中

任何导航器都未处理有效负载为";params";:{";roomId";:";...";}}的导航操作

窄SomeType与SomeType[]

我可以使用JsDocs来澄清Typescript实用程序类型吗?

基于泛型类型的条件类型,具有条目属性判断