To detect a route change in Next.js:
app
directory: useuseEffect
andusePathname
.pages
directory: useuseEffect
anduseRouter
.
Listen for route/page change in Next.js app
directory
To listen for a route change in Next.js 13 app
directory, use the useEffect
and the usePathname
hooks. The action in useEffect
will run anytime the pathname from usePathname
changes.
'use client';
import { usePathname } from 'next/navigation';
import { useEffect, useState } from 'react';
export function RouteChangeListener() {
const pathname = usePathname();
const [changes, setChanges] = useState(0);
useEffect(() => {
console.log(`Route changed to: ${pathname}`);
setChanges((prev) => prev + 1);
}, [pathname]);
return <></>;
}
Here we log to the console and change the state of the component when the route changes.
Page change listener must persist with client-side routing
For this detection to work, the component containing this useEffect
needs to be somewhere in the DOM where it will not get unmounted with client-side navigation.
In the Next.js 13 app
directory, this could be the layout.tsx
file:
import { Metadata } from 'next';
import '@/styles/globals.css';
import { RouteChangeListener } from './route-change-listener';
export const metadata: Metadata = {
title: 'Coding Beauty',
description: 'The official Coding Beauty home page.',
icons: {
icon: '/favicon.png',
},
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
{/* 👇 Persists with client-side navigation */}
<RouteChangeListener />
<body>{children}</body>
</html>
);
}
useEffect
needs 'use client'
Also, since server components are the default in Next.js 13, you’ll need to add the 'use client'
directive at the top of the component file.
Otherwise, you won’t be able to use interactive client-side features like React hooks, including useEffect
.
Listen for route/page change in Next.js pages
directory
To handle a URL or location change in Next.js pages
directory, combine the useEffect
and the useRouter
hooks:
import { useEffect } from 'react';
import { useRouter } from 'next/router';
export function UrlChangeListener() {
const router = useRouter();
useEffect(() => {
console.log(`The page is now: ${router.pathname}`);
}, [router]);
return <></>;
}
Route change detector must persist with client-side routing
Just like with the app
directory, the component that listens for the URL change with useEffect
needs to be somewhere in the DOM where it will not get unmounted with client-side navigation.
In the pages
directory, this could be the _app.tsx
or _app.js
file:
import '@/styles/globals.css';
import type { AppProps } from 'next/app';
import { UrlChangeListener } from './url-change-listener';
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<UrlChangeListener />
<Component {...pageProps} />
</>
);
}
Detect route/page with useRouter()
events
Alternatively, we can detect a client-side URL change in the Next.js pages
directory with events that the useRouter()
object emits. For example:
import { useEffect } from 'react';
import { useRouter } from 'next/router';
export function UrlChangeListener() {
const router = useRouter();
useEffect(() => {
const startHandler = () => {
console.log('Router change started');
};
const completeHandler = () => {
console.log('Router change completed');
};
router.events.on('routeChangeStart', startHandler);
router.events.on('routeChangeComplete', completeHandler);
return () => {
router.events.off('routeChangeStart', startHandler);
router.events.off('routeChangeComplete', completeHandler);
};
}, []);
// 👇 You can put a progress bar or something here
return <></>;
}
Here we used two important router events:
routeChangeStart
– fires when the route is about to change.routerChangeComplete
– fires when the router has changed completely.
There’s more too, and their names are just as self-explanatory as these two.
Key takeaways
- To listen for a route or page change in Next.js
app
directory, combine theuseEffect
andusePathname
hooks. - Detect a URL change in the
pages
directory with theuseEffect
anduseRouter
hooks. - You can also use the
routeChangeStart
androuteChangeComplete
events from theuseRouter()
object to handle a location change.
11 Amazing New JavaScript Features in ES13
This guide will bring you up to speed with all the latest features added in ECMAScript 13. These powerful new features will modernize your JavaScript with shorter and more expressive code.