I've a navigation bar that scrolls to the page's sections using fragments, e.g:
// nav
<a href="#section_dev">{'Development'}</a>
// somewhere else in the page
<a id="section_dev">{'Development'}</a>
How do I apply a style to the navigation link while active (user is in http://myurl/#section_dev)?
I thought of something like this:
<Link href="#section_dev">
<a
className={router.fragment == '#section_dev' ? styles.active : ''}
>
{'Development'}
</a>
</Link>
But the problem is that this functionality appears to be server side, so the router doesn't know the current fragment.
The current path's fragment is only known on the client-side. This means you have to handle it on the client-side only.
You can start by creating a state variable that you'll use to track the fragment/hash value on the client. Then use an
useEffectto set the variable value to the current path's fragment.The
useEffectis needed to set the initial value becausewindowis not defined when the page gets pre-rendered on the server by Next.js. Trying to set the initial state inuseState()will either cause runtime errors on the server, or hydration mismatches on the client.The above will handle initial page loads that contain the fragment in the URL. If you also need to handle client-side navigations that include the fragment you have to add additional logic for it.
Using
next/router, you can listen for changes in the URL fragment during client-side transitions, then update the existingrouteHashvariable.Here's a codesandbox link showcasing the above solution: https://codesandbox.io/s/brave-frog-uxb515.