From 6677c50f3c8d70143fff71fe0de3dbff25521ec1 Mon Sep 17 00:00:00 2001 From: Kay Lack Date: Thu, 9 May 2024 19:34:29 +0100 Subject: [PATCH] Fix active link highlighting when using custom href formatting Previously when we formatted the `href` attribute (for example, to prefix a `#` when using useHashLocation) this would make it not match the current path, which would not have the hash prefix. This patch preserves the target (href, or to) of the Link component and then compares this value to the active path. This should then match. I have also altered some variable names to improve clarity given we now have four different various 'paths' in this component. Fixes #417 --- packages/wouter/src/index.js | 10 +++++----- packages/wouter/test/link.test.tsx | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/packages/wouter/src/index.js b/packages/wouter/src/index.js index c6b2da7..9012798 100644 --- a/packages/wouter/src/index.js +++ b/packages/wouter/src/index.js @@ -187,11 +187,11 @@ export const Route = ({ path, nest, match, ...renderProps }) => { export const Link = forwardRef((props, ref) => { const router = useRouter(); - const [path, navigate] = useLocationFromRouter(router); + const [currentPath, navigate] = useLocationFromRouter(router); const { to, - href: _href = to, + href: targetPath = to, onClick: _onClick, asChild, children, @@ -219,13 +219,13 @@ export const Link = forwardRef((props, ref) => { _onClick?.(event); if (!event.defaultPrevented) { event.preventDefault(); - navigate(_href, props); + navigate(targetPath, props); } }); // handle nested routers and absolute paths const href = router.hrefs( - _href[0] === "~" ? _href.slice(1) : router.base + _href, + targetPath[0] === "~" ? targetPath.slice(1) : router.base + targetPath, router // pass router as a second argument for convinience ); @@ -236,7 +236,7 @@ export const Link = forwardRef((props, ref) => { onClick, href, // `className` can be a function to apply the class if this link is active - className: cls?.call ? cls(path === href) : cls, + className: cls?.call ? cls(currentPath === targetPath) : cls, children, ref, }); diff --git a/packages/wouter/test/link.test.tsx b/packages/wouter/test/link.test.tsx index 5317954..5208024 100644 --- a/packages/wouter/test/link.test.tsx +++ b/packages/wouter/test/link.test.tsx @@ -226,6 +226,34 @@ describe("active links", () => { expect(element).not.toHaveClass("active"); expect(element).toHaveClass("link"); }); + + it("correctly highlights active links when using custom href formatting", () => { + const formatter = (href: string) => `#${href}`; + const { navigate, hook } = memoryLocation({ path: "/" }); + + const { getByText } = render( + + { + return [isActive ? "active" : "", "link"].join(" "); + }} + > + Click Me + + + ); + + const element = getByText("Click Me"); + expect(element).toBeInTheDocument(); + expect(element).toHaveClass("active"); + expect(element).toHaveClass("link"); + + act(() => navigate("/about")); + + expect(element).not.toHaveClass("active"); + expect(element).toHaveClass("link"); + }); }); describe(" with `asChild` prop", () => {