diff --git a/.changeset/brave-pillows-juggle.md b/.changeset/brave-pillows-juggle.md new file mode 100644 index 0000000000..82820194fd --- /dev/null +++ b/.changeset/brave-pillows-juggle.md @@ -0,0 +1,5 @@ +--- +"react-router-dom": patch +--- + +Fix `NavLink` `isPending` when a `basename` is used diff --git a/packages/react-router-dom/__tests__/nav-link-active-test.tsx b/packages/react-router-dom/__tests__/nav-link-active-test.tsx index f6ba739be1..f437f83f0c 100644 --- a/packages/react-router-dom/__tests__/nav-link-active-test.tsx +++ b/packages/react-router-dom/__tests__/nav-link-active-test.tsx @@ -942,6 +942,46 @@ describe("NavLink using a data router", () => { expect(screen.getByText("Link to Bar").className).toBe(""); expect(screen.getByText("Link to Baz").className).toBe("active"); }); + + it("applies the default 'active'/'pending' classNames when a basename is used", async () => { + let dfd = createDeferred(); + let router = createBrowserRouter( + createRoutesFromElements( + }> + Foo page

} /> + dfd.promise} + element={

Bar page

} + /> +
+ ), + { + window: getWindow("/base/foo"), + basename: "/base", + } + ); + render(); + + function Layout() { + return ( + <> + Link to Foo + Link to Bar + + + ); + } + + expect(screen.getByText("Link to Bar").className).toBe(""); + + fireEvent.click(screen.getByText("Link to Bar")); + expect(screen.getByText("Link to Bar").className).toBe("pending"); + + dfd.resolve(null); + await waitFor(() => screen.getByText("Bar page")); + expect(screen.getByText("Link to Bar").className).toBe("active"); + }); }); describe("NavLink under a Routes with a basename", () => { diff --git a/packages/react-router-dom/index.tsx b/packages/react-router-dom/index.tsx index 9a6ab99f72..532658706e 100644 --- a/packages/react-router-dom/index.tsx +++ b/packages/react-router-dom/index.tsx @@ -1028,7 +1028,7 @@ export const NavLink = React.forwardRef( let path = useResolvedPath(to, { relative: rest.relative }); let location = useLocation(); let routerState = React.useContext(DataRouterStateContext); - let { navigator } = React.useContext(NavigationContext); + let { navigator, basename } = React.useContext(NavigationContext); let isTransitioning = routerState != null && // Conditional usage is OK here because the usage of a data router is static @@ -1053,6 +1053,11 @@ export const NavLink = React.forwardRef( toPathname = toPathname.toLowerCase(); } + if (nextLocationPathname && basename) { + nextLocationPathname = + stripBasename(nextLocationPathname, basename) || nextLocationPathname; + } + // If the `to` has a trailing slash, look at that exact spot. Otherwise, // we're looking for a slash _after_ what's in `to`. For example: //