Loading Screen on Next.js page transition

Cover Image for Loading Screen on Next.js page transition
Ali Bentaleb
In Next.js, for loading screen on page transition you either have to:
  • Subscribe to routeChangeStart, routeChangeComplete and routeChangeError router.events and implement your loading screen.
  • Implement onRouteChangeStart, onRouteChangeComplete and onRouteChangeError methods in Router component.
  • Or simply load a spinner while waiting for page to resolve.

Subscribe to routeChangeStart, routeChangeComplete and routeChangeError

The easy way is to use a framework like nprogress to display loading screen when navigating between pages in a Next.js app.

Install nprogress

To do so, navigate to your project home and type in:

##npm
npm i nprogress
## yarn


yarn add nprogress

Copy nprogress CSS to your project

copy nprogress.css from node_modules/nprogress/nprogress.css to styles/nprogress.css

cp $PROJECT_FOLDER/node_modules/nprogress/nprogress.css $PROJECT_FOLDER/styles/


where $PROJECT_FOLDER is your next.js project directory.

Custom _app.js

Customize your _app.js, so that in every route change, the loading page is displayed, and this will save us time instead of implementing transition for every single page on our project.

Since most transitions like clicking on a link are done in Next.js in client side, we are going to use React hook useEffect which can run on client and detect when a client clicks on a link, then we are going to subscribe to Next.js router.events and fire our progress bar on changing page.

Here is how the code will look like

Create _app.js under pages folder, and copy the following

import '../styles/globals.css';
import '../styles/nprogress.css';

import {useRouter} from 'next/router';

import {useEffect} from 'react';
import NProgress from 'nprogress';

function MyApp({Component, pageProps}) {
	const router = useRouter();

	useEffect(() => {
		router.events.on('routeChangeStart', () => NProgress.start());

		router.events.on('routeChangeComplete', () => NProgress.done());
		router.events.on('routeChangeError', () => NProgress.done());
	}, []);

	return <Component {...pageProps} />;
}
export default MyApp;

Build pages

Create page1.js under pages folder and copy the following:

import Link from 'next/link';
export default function () {
	return (
		<div>
			{' '}
			<Link href="/page2">page 2</Link>
		</div>
	);
}

Create page2.js under pages folder and copy the following:

import Link from 'next/link';
export default function () {
	return (
		<div>
			{' '}
			<Link href="/page1">page 1</Link>
		</div>
	);
}

Test loading screen on page transition

Now, hit localhost:3000/page1 and click the link (page 1), you should see blue progress bar on top in page transition and a spinning circle at top right corner of the screen.

You can click back on link (page 2) and repeat as much as you want :)

Bingo

nextjs project with nprogress bar in page transition

Implement onRouteChangeStart, onRouteChangeComplete and onRouteChangeError

If you wish to implement onRouteChangeStart, onRouteChangeComplete and onRouteChangeError when using Next.js Router component, you can follow the same approach, and with some tricks below you can redo the same.

Create _app.js and copy the following:

import '../styles/globals.css';
import '../styles/nprogress.css';
import Router from 'next/router';
import {useEffect} from 'react';
import NProgress from 'nprogress';

function MyApp({Component, pageProps}) {
	useEffect(() => {
		Router.onRouteChangeStart = () => {
			NProgress.start();
		};
		Router.onRouteChangeComplete = () => {
			NProgress.done();
		};
		Router.onRouteChangeError = () => {
			NProgress.done();
		};
	}, []);

	return <Component {...pageProps} />;
}
export default MyApp;

Load a spinner while waiting for page to resolve

We can also display custom spinners using tailwindcss, to do so; you can use my spinner in this link.

Now, to see the spinner, the page components should be delayed some time to give the spinner the time to display

Delayed rendering of React components

To delay rendering of our React component, we use:

  • Node.js setTimeout, when the timeout ends, it will change state of our React state variable.
  • useState to switch component once timeout has finished and display next component.

Create spin.js under pages folder and copy the below:

import Spinner from '../components/spinner';
import React, {useState} from 'react';
import Link from 'next/link';

export default function () {
	const [delay, setDelay] = useState(0);

	setTimeout(() => setDelay(1), 5000);

	return delay === 0 ? (
		<Spinner />
	) : (
		<div className="h-screen w-full flex justify-center items-center text-blue-400">
			<Link href="/">Next Screen</Link>
		</div>
	);
}

Now hit the URL http://localhost:3000/spin, you should see the spinner spinning for 5 seconds and then vanished and the link is displayed.

The comprehensive guide to use...How to send a post request to ...