Highlighting the active link in Next.js nested routes
While building this site I noticed the "Blog" link in the navigation wasn't highlighting when viewing a blog post.
To build the navigation I'm using an array of `navLinks` in my config file.
1export const config = {
2 ...
3 navLinks: [
4 {
5 text: 'Blog',
6 url: '/blog',
7 external: false,
8 },
9 {
10 text: 'Github',
11 url: 'https://github.com/AidanZealley',
12 external: true,
13 }
14 ],
15 ...
16}
The `pathname` field from `useRouter` wasn't matching the `/blog` url in my config file while on a url like `/blog/my-blog-post`.
I wrote a function to compare only the first part of the `pathname` against the url in the config.
1const isSameSiteSection = (path, configUrl) => `/${path.split('/')[1]}` === configUrl
Now I use the value of that function to conditionally add the active link class.
Full Nav component
1import Link from 'next/link'
2import { useRouter } from 'next/router'
3import OpenInNewRoundedIcon from '@material-ui/icons/OpenInNewRounded'
4import { config } from '@utils/config'
5import styles from './styles.module.css'
6
7export const Nav = () => {
8 const { navLinks } = config
9 const isSameSiteSection = (path, configUrl) => `/${path.split('/')[1]}` === configUrl
10 const { pathname } = useRouter()
11 return (
12 <nav className={`${styles.nav}`}>
13 {navLinks.map(({ label, url, external }, index) => (
14 <Link key={index} href={url}>
15 <a
16 className={`
17 ${styles.link}
18 ${isSameSiteSection(pathname, url) ? ` ${styles.active}` : ''}
19 `}
20 target={external ? '_blank' : ''}
21 >
22 {label}
23 {
24 external
25 ? <OpenInNewRoundedIcon fontSize="small"/>
26 : ''
27 }
28 </a>
29 </Link>
30 ))}
31 </nav>
32 )
33}