Search code examples
javascriptreactjsnext.jsrouter

Create routeChangeStart and routeChangeComplete router events in next js 14 client side component


I have a next js v14.0.4 project. I'm trying to apply top loader progress bar with NProgress package for each route change that occurs with Link or router.push(). But handleRouteChangeStart and handleRouteChangeComplete functions never trigger. I think the problem is with Router.events.on('routeChangeStart', handleRouteChangeStart) and Router.events.on('routeChangeComplete', handleRouteChangeComplete), but I don't know how to replace them.

'use client';
import React, { useEffect } from 'react';
import { Router } from 'next/router';
import NProgress from 'nprogress'; // Import NProgress
import 'nprogress/nprogress.css'; // Import NProgress styles
import { usePathname } from 'next/navigation';

const TopLoader: React.FC = () => {
const pathname = usePathname();

useEffect(() => {
 const handleRouteChangeStart = (url: string) => {
   console.log(`Route change started: ${url}`);
   // Execute custom logic here on route change start
   NProgress.start();
 };

 const handleRouteChangeComplete = (url: string) => {
   console.log(`Route change completed: ${url}`);
   NProgress.done();
   // Execute custom logic here on route change complete
 };

 // Listen to route change start
 Router.events.on('routeChangeStart', handleRouteChangeStart);

 // Listen to route change complete
 Router.events.on('routeChangeComplete', handleRouteChangeComplete);

 return () => {
   // Clean up event listeners when the component unmounts
   Router.events.off('routeChangeStart', handleRouteChangeStart);
   Router.events.off('routeChangeComplete', handleRouteChangeComplete);
 };
}, [pathname]); // Only re-run effect if pathname changes

useEffect(() => {
 // Clean up NProgress on component unmount
 return () => {
   NProgress.remove();
 };
}, []);

return null;
};

export default TopLoader;

Solution

  • Firstly, in NextJs app router you should use the router from next/navigation not next/router which is for pages directory. That said router events are no longer supported in the app router but you can surely implement the loading progress for the app router using NProgress library which i have implemented myself as well with some reference. I tried to find the reference but couldn't but you can still take a look at my code here.

    Few explanations:

    • In the implementation, we are creating a wrapper for the useRouter hook and Link component to support loading progress. Now instead of importing from next/navigation, you use those wrapper.
    • Instead of installing the nprogress package, I have copied its content and used from there.
    • Make sure to copy all the files inside custom-router folder for it to work and also make sure to add HandleOnComplete inside route-change-complete.tsx file to your root layout.

    Leave a comment for follow up questions or issues.