Loading Spinner in Next.js – Axios Interceptor & Routing Navigation Loader

In this guide, we will learn how to implement a custom Next JS Loading Spinner component. This Loading Spinner can easily be customized according to your theme. Also, we will discuss how to easily integrate it with Routing transition and HTTP calls as Axios-based Interceptors to indicate users with Spinner loader.   The Loading Spinner…

By.

•

min read

In this guide, we will learn how to implement a custom Next JS Loading Spinner component. This Loading Spinner can easily be customized according to your theme.

Also, we will discuss how to easily integrate it with Routing transition and HTTP calls as Axios-based Interceptors to indicate users with Spinner loader.

 

The Loading Spinner plays an important role in user-faced applications to indicate if there is any process currently going on. When we transition between pages or fetch data, it’s important to intimate the user about the ongoing process.

Let’s dive in and explore how to implement and customize a loading spinner in Next.js.

 

How to create Custome Loading Spinner in the Next js application?

Follow this step-by-step tutorial to create a customer Spinner loading component. Thereafter we will discuss how to use this Spinner component in navigation transition and watch HTTP calls using Axios based interceptor:

Step 1: Setup Next JS Application

Step 2:

 

 

Step 1: Setup Next JS Application

For easy to understand process, we will create a new Next JS application. If you already have one, just go with that and jump to next steps.

You can create a new Next.js application by running the following command in your terminal:

npx create-next-app@11 next-js-loading-spinner

This command uses npx to run the create-next-app to create a new Next.js application in a directory called next-js-loading-spinner.

 

Navigate into your new project directory:

cd next-js-loading-spinner

 

You can run the Next js application by executing the below command app application root folder:

npm run dev

 

Step 2: Creating the Spinner Component

Let’s create a new component for our spinner. In the components directory, create a new file called Spinner.js.

In this file, we will create a functional component that will return a simple div with a class named spinner. This div will act as our loading spinner:

// components/Spinner.js

import styles from "../styles/Spinner.module.css";

function Spinner() {
  return (
    <div className={styles.overlay}>
      <div className={styles.spinner}></div>
    </div>
  );
}

export default Spinner;

 

Step 2: Styling the Spinner

Next, we will add some basic CSS styles to spinner. In the styles directory, create a new CSS file called Spinner.module.css.

In this file, add the following styles to make our div look like a spinner. We’ll use CSS animations to create a spinning effect.

/* styles/Spinner.module.css */

.overlay {
  position: fixed;
  display: flex;
  justify-content: center;
  align-items: center;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 9999;
}

.spinner {
  border: 16px solid #f3f3f3;
  border-top: 16px solid #3498db;
  border-radius: 50%;
  width: 120px;
  height: 120px;
  animation: spin 2s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

 

The above style will create a spinner loader component which will look like this:

next js spinner loader routing interceptor-example-freakyjolly.com1

 

Step 3: Show Spinner on Page Routing / Transitions

Now we will deploy the spinner to be displayed during page transitions. We will use the useRouter hook from Next.js, which allows us to access the router object and its properties.

In the _app.js file, import Spinner component and the useRouter hook. Then use the router.events property to listen for route change events and display our spinner.

// pages/_app.js

import { useState, useEffect } from "react";
import { useRouter } from "next/router";
import Spinner from "../components/Spinner";

function MyApp({ Component, pageProps }) {
  const router = useRouter();
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    const handleStart = () => {
      setLoading(true);
    };
    const handleComplete = () => {
      setLoading(false);
    };

    router.events.on("routeChangeStart", handleStart);
    router.events.on("routeChangeComplete", handleComplete);
    router.events.on("routeChangeError", handleComplete);

    return () => {
      router.events.off("routeChangeStart", handleStart);
      router.events.off("routeChangeComplete", handleComplete);
      router.events.off("routeChangeError", handleComplete);
    };
  }, [router]);

  return (
    <>
      {loading && <Spinner />}
      <Component {...pageProps} />
    </>
  );
}

export default MyApp;

In the above code, we are using the useState and useEffect hooks from React to manage our loading state and listen for route change events.

When a route change starts, we set loading to true, and when it completes or if there’s an error, we set loading to false, which removes the Spinner from the screen.

 

Create Pages for Testing

Finally, let’s create two sample pages, Page1.js and Page2.js, and add links to navigate between them:

// pages/Page1.js

import Link from 'next/link';

function Page1() {
  return (
    <div>
      <h1>Page 1</h1>
      <Link href="/Page2">Go to Page 2</Link>
    </div>
  );
}

export default Page1;
// pages/Page2.js

import Link from 'next/link';

function Page2() {
  return (
    <div>
      <h1>Page 2</h1>
      <Link href="/Page1">Go to Page 1</Link>
    </div>
  );
}

export default Page2;

 

Update Index Page

Thereafter we will update the index.js page, which acts as a landing page for the new Next js application.

// pages/index.js

import Link from "next/link";
import { useAxios } from "../utils/axios";
import { useState } from "react";

function Home() {
  const [axios, spinner] = useAxios();
  const [data, setData] = useState(null);

  const handleFetchData = async () => {
    const response = await axios.get(
      "https://jsonplaceholder.typicode.com/posts"
    );
    setData(response.data);
  };

  return (
    <div>
      <h1>Home</h1>
      <Link href="/Page1">Go to Page 1</Link>
      <br />
      <Link href="/Page2">Go to Page 2</Link>
      <br />
      <button onClick={handleFetchData}>Fetch Data</button>
      {spinner}
      {data && <pre>{JSON.stringify(data, null, 2)}</pre>}
    </div>
  );
}

export default Home;

This file will have links to page 1 and page 2. Now whenever you navigate from one page to another, you will see the Spinner loading element in your Next js application.

Other than this you will also notice a button to trigger an HTTP call. Currently, this call will not display the spinner loader, as we still need to introduce the HTTP call interceptor. Which we will discuss in the next section.

 

Step 4: Show Spinner on HTTP Calls using Axios Interceptor

In this step, you will how to add an HTTP interceptor in the Next js application using the Axios library. This HTTP interceptor will be created once and watch each and every HTTP call of every type including POST, GET etc to show Spinner Loader.

This Axios interceptor will keep a watch on each and every HTTP remote API call and show/ hide the Spinner Loader component which we create as a custom component.

Follow these steps to set up the Next js app to create an Axios interceptor and use it in HTTP calls:

First, install axios using npm:

npm install axios

 

Then, create a new axios.js file inside the utils folder at your application root folder:

// utils/axios.js

import axios from 'axios';
import { useState } from 'react';
import Spinner from '../components/Spinner';

const instance = axios.create();

export const useAxios = () => {
  const [loading, setLoading] = useState(false);

  instance.interceptors.request.use(function (config) {
    setLoading(true);
    return config;
  }, function (error) {
    setLoading(false);
    return Promise.reject(error);
  });

  instance.interceptors.response.use(function (response) {
    setLoading(false);
    return response;
  }, function (error) {
    setLoading(false);
    return Promise.reject(error);
  });

  return [instance, loading ? <Spinner /> : null];
};

export default instance;

In this file, we’re creating a custom useAxios hook that returns an axios instance and a loading spinner. The Axios instance is configured with request and response interceptors that set the loading state to true before a request and to false after a response or an error.

You can then use this useAxios hook in your components to make HTTP requests:

// pages/index.js

import Link from 'next/link';
import { useAxios } from '../utils/axios';
import { useState } from 'react';

function Home() {
  const [axios, spinner] = useAxios();
  const [data, setData] = useState(null);

  const handleFetchData = async () => {
    const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
    setData(response.data);
  };

  return (
    <div>
      <h1>Home</h1>
      <Link href="/Page1">Go to Page 1</Link>
      <br />
      <Link href="/Page2">Go to Page 2</Link>
      <br />
      <button onClick={handleFetchData}>Fetch Data</button>
      {spinner}
      {data && <pre>{JSON.stringify(data, null, 2)}</pre>}
    </div>
  );
}

export default Home;

 

Step 5: Customizing the Loading Spinner

Now that we have a basic loading spinner in place, let’s look at how we can customize it to better match the look and feel of our application. Customizing the loading spinner can be done primarily through CSS.

 

Changing the Size of the Spinner

The size of the spinner can be adjusted by changing the width and height properties in the CSS.

.spinner {
  ...
  width: 60px;
  height: 60px;
  ...
}

 

Changing the Color of the Spinner

The colour of the spinner can be changed by modifying the border-top property.

.spinner {
  ...
  border-top: 16px solid red;
  ...
}

 

Changing the Speed of the Spinner

Speed of the spinning animation can be adjusted by changing the duration of the spin animation in the CSS. A smaller value will make the spinner spin faster, while a larger value will make it spin slower:

.spinner {
  ...
  animation: spin 1s linear infinite; /* Faster */
  ...
}

 

Conclusion

We discussed how to easily create a custom Spinner Loader component in the Next js application. The Spinner loading component is used in the Router navigation to indicate users while page transitions.

The most important use case is to display the loader Spinner when we make an HTTP Call to fetch data. For that, we create an Axios-based interface, which can easily be created once and used everywhere to show the Spinner loader whenever any kind of HTTP call is triggered.

The Spinner component we created, can easily be customized with your own style and looks. The Spinner is shown as an overlay in the centre of page with a backdrop to prevent users to take any action till the current action is completed.

There are also many other ways to indicate users about the loading process like using the linear progress bar on the page top like YouTube using the NProgress which you can check here.

Leave a Reply

Your email address will not be published. Required fields are marked *