Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Target Active Link when the route is active in Next.js

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?

like image 837
Ruby Avatar asked Nov 12 '18 12:11

Ruby


People also ask

How do I style a link in next JS?

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.

How do I use react router in NextJs?

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.


2 Answers

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.

like image 70
Rotareti Avatar answered Sep 28 '22 08:09

Rotareti


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

like image 33
Darryl RN Avatar answered Sep 28 '22 07:09

Darryl RN