How to show a loader when navigating between pages in Next.js

Photo by Mike van den Bos on Unsplash

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):

Data fetching in Server-side Rendering

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.

Next.js router events

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.

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

NavigationLoader React Component

CSS

NavigationLoader CSS

Result

Loading overlay

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

_app.js

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!

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store