Skip to content

Commit 5ec6700

Browse files
authored
NavLink: replace activeClassName + activeStyle props (#7985)
1 parent 02d09a9 commit 5ec6700

File tree

4 files changed

+163
-273
lines changed

4 files changed

+163
-273
lines changed

docs/advanced-guides/migrating-5-to-6.md

Lines changed: 66 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,22 @@ In general, the process looks like this:
2727
- Use `<Route children>` everywhere
2828
- Use hooks instead of `withRouter` and "floating" `<Route>`s (that aren't
2929
part of a `<Switch>`)
30-
- [Upgrade to React Router v6](#upgrade-to-react-router-v6)
31-
- [Upgrade all `<Switch>` elements to `<Routes>`](#upgrade-all-switch-elements-to-routes)
32-
- Update `<Link to>` values
33-
- Update `<Route path>` patterns
34-
- Remove `<Route exact>` and `<Route strict>` props
35-
- Move `<Route sensitive>` to containing `<Routes caseSensitive>`
36-
- Consolidate your `<Route>`s into a nested config (optional)
37-
- [Use `navigate` instead of `history`](#use-navigate-instead-of-history)
38-
- Use `useNavigate` hook instead of `useHistory`
39-
- Use `<Navigate>` instead of `<Redirect>`
40-
- [Use `useRoutes` instead of `react-router-config`](#use-useroutes-instead-of-react-router-config)
30+
- [Migrating React Router v5 to v6](#migrating-react-router-v5-to-v6)
31+
- [Upgrade to React v16.8](#upgrade-to-react-v168)
32+
- [Upgrade to React Router v5.1](#upgrade-to-react-router-v51)
33+
- [Upgrade to React Router v6](#upgrade-to-react-router-v6)
34+
- [Upgrade all `<Switch>` elements to `<Routes>`](#upgrade-all-switch-elements-to-routes)
35+
- [Relative Routes and Links](#relative-routes-and-links)
36+
- [Advantages of `<Route element>`](#advantages-of-route-element)
37+
- [Note on `<Route path>` patterns](#note-on-route-path-patterns)
38+
- [Note on `<Link to>` values](#note-on-link-to-values)
39+
- [Use useRoutes instead of react-router-config](#use-useroutes-instead-of-react-router-config)
40+
- [Use navigate instead of history](#use-navigate-instead-of-history)
4141
- [Rename `<Link component>` to `<Link as>` and `<NavLink exact>` to `<NavLink end>`](#rename-link-component-to-link-as-and-navlink-exact-to-navlink-end)
42+
- [Remove `activeClassName` and `activeStyle` props from `<NavLink />`](#remove-activeclassname-and-activestyle-props-from-navlink-)
4243
- [Get `StaticRouter` from `react-router-dom/server`](#get-staticrouter-from-react-router-domserver)
4344
- [Move `basename` from `<Router>` to `<Routes>`](#move-basename-from-router-to-routes)
45+
- [What did we miss?](#what-did-we-miss)
4446

4547
## Upgrade to React v16.8
4648

@@ -708,6 +710,59 @@ function SomeForm() {
708710
This is a simple renaming of a prop to better align with the common practice of
709711
other libraries in the React ecosystem including styled-components and Reach UI.
710712

713+
## Remove `activeClassName` and `activeStyle` props from `<NavLink />`
714+
715+
As of `v6.0.0-beta.3`, the `activeClassName` and `activeStyle` props have been removed from `NavLinkProps`. Instead, you can pass a function to either `style` or `className` that will allow you to customize the inline styling or the class string based on the component's active state.
716+
717+
```diff tsx
718+
<NavLink
719+
to="/messages"
720+
- style={{ color: 'blue' }}
721+
- activeStyle={{ color: 'green' }}
722+
+ style={isActive => ({ color: isActive ? 'green' : 'blue })}
723+
>
724+
Messages
725+
</NavLink>
726+
```
727+
728+
```diff tsx
729+
<NavLink
730+
to="/messages"
731+
- className="nav-link"
732+
- activeClassName="activated"
733+
+ className={isActive => "nav-link" + (isActive ? " activated" : "")}
734+
>
735+
Messages
736+
</NavLink>
737+
```
738+
739+
If you prefer to keep the v5 props, you can create your own `<NavLink />` as a wrapper component for a smoother upgrade path.
740+
741+
```tsx
742+
import React from "react";
743+
import { NavLink as BaseNavLink } from "react-router-dom";
744+
745+
const NavLink = React.forwardRef(
746+
({ activeClassName, activeStyle, ...props }, ref) => {
747+
return (
748+
<BaseNavLink
749+
ref={ref}
750+
{...props}
751+
className={isActive =>
752+
[props.className, isActive ? activeClassName : null]
753+
.filter(Boolean)
754+
.join(" ")
755+
}
756+
style={isActive => ({
757+
...props.style,
758+
...(isActive ? activeStyle : null)
759+
})}
760+
/>
761+
);
762+
}
763+
);
764+
```
765+
711766
## Get `StaticRouter` from `react-router-dom/server`
712767

713768
The `StaticRouter` component has moved into a new bundle:

docs/api-reference.md

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -341,19 +341,19 @@ TODO: example
341341
```tsx
342342
declare function NavLink(props: NavLinkProps): React.ReactElement;
343343

344-
interface NavLinkProps extends LinkProps {
345-
activeClassName?: string;
346-
activeStyle?: object;
344+
interface NavLinkProps extends Omit<LinkProps, "className" | "style"> {
347345
caseSensitive?: boolean;
346+
className?: string | ((isActive: boolean) => string);
348347
end?: boolean;
348+
style?: React.CSSProperties | ((isActive: boolean) => React.CSSProperties);
349349
}
350350
```
351351

352352
</details>
353353

354-
A `<NavLink>` is a special kind of [`<Link>`](#link) that knows whether or not it is "active". This is useful when building a navigation menu such as a breadcrumb or a set of tabs where you'd like to show which of them is currently selected.
354+
A `<NavLink>` is a special kind of [`<Link>`](#link) that knows whether or not it is "active". This is useful when building a navigation menu such as a breadcrumb or a set of tabs where you'd like to show which of them is currently selected. It also provides useful context for assitive technology like screen readers.
355355

356-
Both `<NavLink activeClassName>` and/or `<NavLink activeStyle>` are applied to the underlying `<Link>` when the route it links to is currently active.
356+
By default, an `active` class is added to a `<NavLink>` component when it is active. This provides the same simple styling mechanism for most users who are upgrading from v5. One difference as of `v6.0.0-beta.3` is that `activeClassName` and `activeStyle` have been removed from `NavLinkProps`. Instead, you can pass a function to either `style` or `className` that will allow you to customize the inline styling or the class string based on the component's active state.
357357

358358
```tsx
359359
import React from "react";
@@ -370,12 +370,18 @@ function NavList() {
370370
<nav>
371371
<ul>
372372
<li>
373-
<NavLink to="messages" activeStyle={activeStyle}>
373+
<NavLink
374+
to="messages"
375+
style={isActive => (isActive ? activeStyle : undefined)}
376+
>
374377
Messages
375378
</NavLink>
376379
</li>
377380
<li>
378-
<NavLink to="tasks" activeStyle={activeStyle}>
381+
<NavLink
382+
to="tasks"
383+
style={isActive => (isActive ? activeStyle : undefined)}
384+
>
379385
Tasks
380386
</NavLink>
381387
</li>
@@ -385,9 +391,36 @@ function NavList() {
385391
}
386392
```
387393

388-
If the `end` prop is used, it will ensure this component isn't matched as "active" when its descendant paths are matched:
394+
If you prefer the v5 API, you can create your own `<NavLink />` as a wrapper component:
395+
396+
```tsx
397+
import React from "react";
398+
import { NavLink as BaseNavLink } from "react-router-dom";
389399

400+
const NavLink = React.forwardRef(
401+
({ activeClassName, activeStyle, ...props }, ref) => {
402+
return (
403+
<BaseNavLink
404+
ref={ref}
405+
{...props}
406+
className={isActive =>
407+
[props.className, isActive ? activeClassName : null]
408+
.filter(Boolean)
409+
.join(" ")
410+
}
411+
style={isActive => ({
412+
...props.style,
413+
...(isActive ? activeStyle : null)
414+
})}
415+
/>
416+
);
417+
}
418+
);
390419
```
420+
421+
If the `end` prop is used, it will ensure this component isn't matched as "active" when its descendant paths are matched:
422+
423+
```tsx
391424
<NavLink to="/" end>Home</NavLink>
392425
```
393426

0 commit comments

Comments
 (0)