Shallow Routing in Nextjs using useRouter and usePathname
Next.js uses the file system to enable routing in the app. Next automatically treats every file with the extensions .js
, .jsx
, .ts
, or .tsx
under the pages
directory as a route.
Shallow routing allows you to change the URL without running data fetching methods again. This can be useful when you need to change the URL for client-side navigation without fetching new data.
Caveats
Shallow routing only works for URL changes in the current page. For example, let’s assume we have another page called pages/about.js
, and you run this:
router.push('/?counter=10', '/about?counter=10', { shallow: true });
Since that’s a new page, it’ll unload the current page, load the new one and wait for data fetching even though we asked to do shallow routing.
Here’s an example of how you can use useRouter
for shallow routing:
// Import the necessary modules from Next.js
import { useRouter } from 'next/router';
import Link from 'next/link';
// Your component
function About() {
// Get the router object
const router = useRouter();
// Handle the click event for the link
const handleClick = () => {
// Use the push method with the shallow option
router.push('/your-route', undefined, { shallow: true });
};
return (
<div>
<p>Current Path: {router.pathname}</p>
{/* Use Link for client-side navigation */}
<Link href="/your-route" shallow>
<a onClick={handleClick}>Go to Your Route</a>
</Link>
</div>
);
}
export default About;
In the example above:
useRouter
is used to get the router object.router.push('/your-route', undefined, { shallow: true })
is used to navigate to the specified route with shallow routing.
Additionally, the Link
component is used for client-side navigation. The shallow
prop is set to true
to enable shallow routing for that specific link.
When shallow routing is used with middleware it will not ensure the new page matches the current page like previously done without middleware. This is due to middleware being able to rewrite dynamically and can’t be verified client-side without a data fetch which is skipped with shallow, so a shallow route change must always be treated as shallow.