How to highlight links to the active route in Next.js
By Richard Thombs on 3/5/2021
Next.js' <Link>
component doesn't include the ability to highlight links that point to the currently active route. Thankfully it is easy to create a component that does:
import Link from "next/link";
import { useRouter } from "next/router";
import { Children, cloneElement } from "react";
export default function LinkActive({ children, ...props }) {
const router = useRouter();
const { href, activeClassName } = props;
// Wrap string-only child in an anchor tag
const child = typeof children === "string" ? <a>{children}</a> : Children.only(children);
// Determine if the route or a child route is active
const isRouteActive = router.asPath === href || router.asPath.startsWith(href + "/");
// Add the activeClassName when the route is active
let className = child.props.className || "";
if (isRouteActive && className && activeClassName) className += " " + activeClassName;
else if (isRouteActive && activeClassName) className = activeClassName;
// Clone the child so we can add className to the props
const clone = cloneElement(child, { className });
return (
<Link {...props}>{clone}</Link>
);
}
How it works
useRouter().asPath
is used to get hold of the currently active path, which contains the URL without the protocol or host. Eg: something like /blog/my-blog-post-title
.
If the path exactly matches the href
parameter, or if the path begins with the href
, then the link is considered active and the activatedClassName
property is appended to the
className
of the child component.
The final result is wrapped in Next's own <Link>
component to provide all the additional functionality.