How to quickly listen for a route/page change in Next.js
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
.
useEffect
can't work without 'use client' in Next.js.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.
See also
- How to allow all domains for images in Next.js
- How to quickly redirect to another page URL in Next.js
- How to Detect a URL Change With JavaScript
- How to check if a variable is null or undefined in React
- How to quickly get the union of two Sets in JavaScript
- How to quickly get the union of two arrays in JavaScript