'Missing isActive prop on NavLink of React Router v6

NavLink component of react-router-dom package supports adding extra logic for determining whether the link is active. At least this was supported in older version. Here is link to documentation: https://reactrouter.com/web/api/NavLink/isactive-func

Code snippet:

<NavLink
  to="/events/123"
  isActive={(match, location) => {
    if (!match) {
      return false;
    }

    // only consider an event active if its event id is an odd number
    const eventID = parseInt(match.params.eventID);
    return !isNaN(eventID) && eventID % 2 === 1;
  }}
>
  Event 123
</NavLink>

It seems like isActive property is not supported anymore in version 6. What are other options to achieve the same thing?



Solution 1:[1]

NavLink activeClassName prop does not exist anymore. With that prop you could pass a class for that specific Link to be modified with some CSS to show that it's become active, like this:

export function Header() {
  return (
    <header>
      <ul>
        <li>
          <NavLink activeClassName="active" to="/about" />
        </li>
        <li>
          <NavLink activeClassName="active" to="/profile" />
        </li>
      </ul>
    </header>
  )
}

With V6 you have to manually do that and you can by passing a function to the className prop we have on React, like this:

export function Header() {
  return (
    <header>
      <ul>
        <li>
          <NavLink className={(navData) => navData.isActive ? "active" : "" } to="/about" />
        </li>
        <li>
          <NavLink className={(navData) => navData.isActive ? "active" : "" } to="/profile" />
        </li>
      </ul>
    </header>
  )
}

Solution 2:[2]

From the source code of react-router-dom v6.0.0-beta.0, isActive now seems to be automatic.

 /**
 * A <Link> wrapper that knows if it's "active" or not.
 */
export const NavLink = React.forwardRef<HTMLAnchorElement, NavLinkProps>(
  function NavLinkWithRef(
    {
      'aria-current': ariaCurrentProp = 'page',
      activeClassName = 'active',
      activeStyle,
      caseSensitive = false,
      className: classNameProp = '',
      end = false,
      style: styleProp,
      to,
      ...rest
    },
    ref
  ) {
    let location = useLocation();
    let path = useResolvedPath(to);

    let locationPathname = location.pathname;
    let toPathname = path.pathname;
    if (!caseSensitive) {
      locationPathname = locationPathname.toLowerCase();
      toPathname = toPathname.toLowerCase();
    }

    let isActive = end
      ? locationPathname === toPathname
      : locationPathname.startsWith(toPathname);

    let ariaCurrent = isActive ? ariaCurrentProp : undefined;
    let className = [classNameProp, isActive ? activeClassName : null]
      .filter(Boolean)
      .join(' ');
    let style = { ...styleProp, ...(isActive ? activeStyle : null) };

    return (
      <Link
        {...rest}
        aria-current={ariaCurrent}
        className={className}
        ref={ref}
        style={style}
        to={to}
      />
    );
  }
);

Here

let isActive = end
          ? locationPathname === toPathname
          : locationPathname.startsWith(toPathname);

So to achieve the same you need to use your own style

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ouflak
Solution 2 Safi Nettah