Optimizing Next.js Routing with Progress Indicators
Next.js has solidified its position as the most popular backend framework built on React. With recent updates, it has become even more robust. One notable feature is its ability to render pages on both the server side and client side, along with its integrated routing system. However, transitioning between these renderers can be slow, resulting in a poor user experience. In this article, we’ll explore how to build and display a progress bar indicator when changing routes in a Next.js application.
Prerequisites
- Fundamental knowledge of Next.js and React
- Basic understanding of the Next.js Routing system
Understanding Next.js Router Events
Router events are event listeners that allow us to track route changes in Next.js via the Router object. The object provides properties that we can use to listen to different events happening in the Next.js Router and perform certain actions based on the events.
Some supported Next.js Router events include:
routeChangeStart
: fires when a route starts to change
routeChangeComplete
: fires when a route change is completed
routeChangeError
: fires when an error occurs while changing routes, or when a route load is canceled
Creating the Loader Component
To display a progress bar indicator, we need to create a component that will wrap the progress indicator element. We’ll create a Loader.js
file and add the following code:
“`jsx
import styles from ‘../styles/loader.module.css’;
const Loader = () => {
return (
);
};
export default Loader;
“`
Creating the Router Events
We’ll call the Router event listeners directly inside the _app.js
component. We’ll import the Router object, useState
, and useEffect
Hooks inside the _app.js
component.
“`jsx
import { useRouter } from ‘next/router’;
import { useState, useEffect } from ‘react’;
import Loader from ‘../components/Loader’;
function App({ Component, pageProps }) {
const router = useRouter();
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
router.events.on(‘routeChangeStart’, () => {
setIsLoading(true);
});
router.events.on('routeChangeComplete', () => {
setIsLoading(false);
});
router.events.on('routeChangeError', () => {
setIsLoading(false);
});
}, []);
return (
<>
{isLoading && }
>
);
}
export default App;
“`
Adding Animation
We can add animation using two libraries: NProgress and React Spinners.
Using NProgress
NProgress is a lightweight library that lets us display realistic trickle animations at the top of the viewport to indicate loading progress. We’ll import the NProgress function inside the _app.js
component and call the function’s start()
and done()
methods inside the routeChangeStart
and routeChangeComplete
event callbacks, respectively.
“`jsx
import NProgress from ‘nprogress’;
// …
router.events.on(‘routeChangeStart’, () => {
NProgress.start();
});
router.events.on(‘routeChangeComplete’, () => {
NProgress.done();
});
“`
Using React Spinners
React Spinners is a lightweight library comprised of a collection of React-based progress indicators. We’ll import a spinner component inside the Loader.js
component and nest the spinner component inside the wrapper div.
“`jsx
import { Puff } from ‘react-spinners’;
const Loader = () => {
return (