NProgress and Router Events with NextJs

Written on 2023-03-24 by Adam Drake - 5 min read

Image of NProgress and Router Events with NextJs

Keeping your user informed via UI events is really important in any Web Application. It provides users with visual cues to indicate that the website is still in progress and will eventually be ready. It also reduces user frustration, as users can understand what is happening in the background and easily track progress. Furthermore, it helps to create a positive user experience and can help keep users on the website longer. So taking care of this is very important if you wish for users to continue to use and return to your web site.

With Nextjs - which I love btw!! - there is one thing that really bugs me and that is the pause when changing routes when the route is doing some data fetch on the server side.

It provides users with visual cues to indicate that the website is still in progress and will eventually be ready. It also reduces user frustration, as users can understand what is happening in the background and easily track progress.

With Nextjs, when landing on a route which has data fetching from the server side, there is a pause on the client side where nothing happens until the data is fetched. Once the data is fetched the data is passed down via props and then the page can be rendered and sent to the client.

Something like this:

type Props = {
  posts: Post[];
};

export default function BlogIndex({ posts }: Props) {
  return (
    <>
      <Head>
        <title>{SITE_NAME} | Blog</title>
      </Head>
      <PageContainer maxWidth="1000px">
          <BlogPageContainer posts={posts} />
      </PageContainer>
    </>
  );
}

export async function getStaticProps() {
  const posts = await client.fetch(
    `*[_type == "post"] | order(_createdAt desc)`,
  );

  return {
    props: {
      posts,
    },
  };
}

This means when the page does load on the client side it has all the data there already which is good. However, that time in between where the user clicked to go to a certain route and the page actually rendering can lead to confusion on the user's behalf because it can seem like nothing is happening.

With Nextjs, if when landing on a route which has data fetching from the server side, this leads to a pause on the client side where nothing happens until the data is fetched.

Using NProgress

That's where I like to use a library like Nprogress. This is a slim progress bar that renders on the UI upon loading a route and shows to the user that something is actually happening. It has been used on major sites like Youtube, Github and Medium.

How to use NProgress in Nextjs

In order to use NProgress (or some other similar library) on Nextjs you have to hook into Nextjs's router events. You can get access to Nextjs's router using the following import:

import Router from 'next/router';

This gives you a `Router` object which has an `events` object on it. With this you can hook into events on the Nextjs router and then call certain functions upon these events.

With our use case we want to call certain functions on the NProgress library:

Router.events.on('routeChangeStart', url => {
  NProgress.start();
});

Router.events.on('routeChangeComplete', () => NProgress.done());

Router.events.on('routeChangeError', () => NProgress.done());

Here we are using three different events on the Nextjs router. The routeChangeStart event, the routeChangeComplete event and the routeChangeError event. In each case we are calling different NProgress functions.

By hooking into the Nextjs router events we are able to show the user that something is happening when they click on certain routes which are waiting for data fetches on the server side.

So when the routeChangeStart event is called we start the NProgress library. This triggers the progress bar to start on the UI. In order to see it though you need to add the css for the NProgress library also.

All of these can be placed in the `_app.tsx` file in your Nextjs project.

<link
  rel="stylesheet"       href="https://cdnjs.cloudflare.com/ajax/libs/nprogress/0.2.0/nprogress.min.css"
  integrity="sha512-42kB9yDlYiCEfx2xVwq0q7hT4uf26FUgSIZBK8uiaEnTdShXjwr8Ip1V4xGJMg3mHkUt9nNuTDxunHF0/EgxLQ=="
  crossOrigin="anonymous"
          />

I placed this in the `_document.tsx` file. Once the route has loaded the routeChangeComplete event is called and then the Nprogress `done()` function is called which completes the progress bar UI.

By hooking into the Nextjs router events we are able to show the user that something is happening when they click on certain routes which are waiting for data fetches on the server side. Great!

Conclusion

Nextjs can be great, but it's not perfect - there is a pause when changing routes when the route has to fetch data from the server, which the user may find confusing. By adding in some UI which is triggered by the Nextjs Router object it can alleviate this confusion and make your users's experience much more pleasant.

Find out more about `next/router` on the official Nextjs docs.

Loading...

Adam Drake AI Selfie

Written by Adam Drake

Adam Drake is a Frontend React Developer who is very passionate about the quality of the web. He lives with his wife and three children in Prague in the Czech Republic.

Adam Drakes Site © 2024