/

Using the router to detect the active link in Next.js

Using the router to detect the active link in Next.js

When working with links in Next.js, it’s important to determine the current URL and assign a class to the active link so that it can be styled differently. This is particularly useful in the site header. Unfortunately, the default Link component provided by next/link doesn’t handle this automatically. However, there are two techniques that we can use to achieve this behavior.

The first technique is to add the logic to the children of the Link component. Here’s a simple example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import React from 'react'
import Link from 'next/link'
import { useRouter } from 'next/router'

const menu = [
{ title: 'Home', path: '/home' },
{ title: 'Explore', path: '/explore' },
{ title: 'Notifications', path: '/notifications' },
]

const Sidebar = () => {
const router = useRouter()

return (
<div>
{menu.map((item, index) => (
<Link key={index} href={item.path}>
<a
className={`cursor-pointer ${
router.pathname === item.path
? 'text-blue-500'
: 'hover:bg-gray-900 hover:text-blue-500'
}`}
>
{item.title}
</a>
</Link>
))}
</div>
)
}

export default Sidebar

This technique is recommended as it is the simplest approach.

The second technique involves creating our own Link component. We can store it in a file called MyLink.js inside the /components folder and import it instead of the default next/link. Inside the component, we compare the current pathname with the href prop of the component. If they match, we append the text-blue-500 class to the children. You can use your own classes, but in this example, we use a Tailwind class to make the text blue. Finally, we return the children with the updated class using React.cloneElement().

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React from 'react'
import Link from 'next/link'
import { useRouter } from 'next/router'

const MyLink = ({ href, children }) => {
const router = useRouter()

let className = children.props.className || ''
if (router.pathname === href) {
className = `${className} text-blue-500`
}

return <Link href={href}>{React.cloneElement(children, { className })}</Link>
}

export default MyLink

Now, we can use this MyLink component in other components:

1
2
3
4
5
6
7
8
9
10
import MyLink from 'components/MyLink'

// ...

<MyLink href="blog">
<a>Blog</a>
</MyLink>
<MyLink href="about">
<a>About</a>
</MyLink>

Using this technique, the code in your other components becomes simpler compared to the first technique, as the logic is now contained within the MyLink component.

tags: [“Next.js”, “Router”, “Active Link”, “CSS styling”, “Components”]