How to show a loader when navigating between pages in Next.js
In this article we will implement a NavigationLoader
component that will be displayed whiled navigating between two Next.js pages.
Introduction
Next.js is an amazing framework for creating React applications, with built in support for features such as server side rendering, static website generation and full Typescript support. It is an ideal framework for creating landing pages, blogs, portfolios or ecommerce websites.
When using Next.js, there are two different approaches to pre-rendering pages: traditional Server-side Rendering and Static Regeneration:
Server-side Rendering (SSR)
The HTML for the page is generated on each request.
Static Generation (SG)
The HTML is generated at build time and it will be reused on every request (cached). When it comes to this approach, the Next.js team also built Incremental Static Regeneration (ISR), which allows the creation or updating of static pages after the site is built, without the need to rebuild the entire site. This is an extremely powerful feature, especially for large websites, as it allows you to have the benefits of static pages while being able to scale to an enormous number of pages. You can read more about Incremental Static Regeneration here.
Unless you are building a simple static website, most of the times your pages will depend on external data, therefore you will be using the getStaticProps (for SG or ISR pages) or getServerSideProps (for SSR pages) methods. In case those methods are executed during run time (ISR & SSR) they can take a while to finish, causing a delay before the page is generated.
Let’s look at an example. Consider the following getServerSideProps method for blog post page (pages/blog/[slug].js):

If one of your users clicks a link that points towards a blog post page and getPostData
takes several seconds to finish, he/she will be stuck on the original page without knowing what’s going on.
In the upcoming sections, we will implement a mechanism that allows users to see that your application is in a loading state, being busy creating the next page. Giving this type of feedback to your users is important as otherwise they might consider that the link is incorrect or the navigation is broken.
Listening to router events
Next.js comes with a built in router which you are most likely already using. It is possible to listen to several router events, but for our use case we’ll focus on just three of them: routeChangeStart
, routeChangeComplete
and routeChangeError
.

routeChangeStart
This event fires when a route starts to change. When this fires, we need to show the loader. As a little improvement, we could actually show the loader with a small delay, to avoid screen flashes for navigation that takes a reasonably short amount of time. We’ll do this by using a setTimeout
.
routeChangeComplete
This even fires when a route change was completed. When this fires, we need to hide the loader.
routeChangeError
This event fires when an error occurs while changing routes or the navigation was cancelled. You won’t stumble across this too often (hopefully!) but it is always good to cover all the possible scenarios. When this fires, we also need to hide the loader. Optionally, based on your needs you could also show an error toast or something similar.
Tip — the callback functions for the events also receive a
url
parameter that you can use to implement route specific behavior, such as not showing the loader for some given routes.
Putting the pieces together
We will create a React component named NavigationLoader
that listens to the router events and renders a full-screen overlay with a semi transparent background and a centered loading text. This overlay will be visible when navigating between pages.
React code
CSS
Result

We want this component to be rendered on every page of our application, thus _app.js
is a great place for adding it:

This is it! When navigating between pages the loading overlay will be shown in case the navigation is taking longer than 250ms.
You can check out the final code and the demo.
Happy coding!