How to target the active Link in Next.js like they way we do it in React-Router-4? Meaning, give the active link a class when its route is active?
In Next. js, <Link> components generally go with <a> tags. To style a link, we don't directly add our CSS class names or inline styles to <Link>. Instead, we do that with the <a> tag.
In React JS, we would install a package called react-router-dom to implement routing inside the application. But Next JS has its own inbuilt router from the next/link , with which we can navigate between the pages. Before using the next/link , we need to set up the different pages/routes inside the pages folder.
A simple solution based on the useRouter
hook:
import Link from "next/link"; import { useRouter } from "next/router"; export const MyNav = () => { const router = useRouter(); return ( <ul> <li className={router.pathname == "/" ? "active" : ""}> <Link href="/">home</Link> </li> <li className={router.pathname == "/about" ? "active" : ""}> <Link href="/about">about</Link> </li> </ul> ); };
You could also use router.asPath
instead of router.pathname
if you want to include the url query parameters. This can be useful if you want to handle anchor tags such as /#about
.
First, you need to have a component called Link, with temporary attribute activeClassName
import { useRouter } from 'next/router' import PropTypes from 'prop-types' import Link from 'next/link' import React, { Children } from 'react' const ActiveLink = ({ children, activeClassName, ...props }) => { const { asPath } = useRouter() const child = Children.only(children) const childClassName = child.props.className || '' // pages/index.js will be matched via props.href // pages/about.js will be matched via props.href // pages/[slug].js will be matched via props.as const className = asPath === props.href || asPath === props.as ? `${childClassName} ${activeClassName}`.trim() : childClassName return ( <Link {...props}> {React.cloneElement(child, { className: className || null, })} </Link> ) } ActiveLink.propTypes = { activeClassName: PropTypes.string.isRequired, } export default ActiveLink
Then have a navigation bar with created component Link and css selector :active
to differentiate between active and inactive link.
import ActiveLink from './ActiveLink' const Nav = () => ( <nav> <style jsx>{` .nav-link { text-decoration: none; } .active:after { content: ' (current page)'; } `}</style> <ul className="nav"> <li> <ActiveLink activeClassName="active" href="/"> <a className="nav-link">Home</a> </ActiveLink> </li> <li> <ActiveLink activeClassName="active" href="/about"> <a className="nav-link">About</a> </ActiveLink> </li> <li> <ActiveLink activeClassName="active" href="/[slug]" as="/dynamic-route"> <a className="nav-link">Dynamic Route</a> </ActiveLink> </li> </ul> </nav> ) export default Nav
After that, you can implement the navigation bar to your page:
import Nav from '../components/Nav' export default () => ( <div> <Nav /> <p>Hello, I'm the home page</p> </div> )
The key of how does this work is located inside component Link, we compare the value of router.pathname
with attribute href
from the Link, if the value match the other then put specific className to make the link looks activated.
Reference: here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With