- Published on
How to show a Loading Indicator on route change in NextJS 13/14 App Router
- Authors
- Name
- Rohan Hussain
Once you've followed this guide, when a user clicks a button or link that initiates a route change, an NProgress
loading indicator will show up instantaneously on the top of the viewport just under the address bar.
Expected Result
You'll see a snake-like loading indicator under the browser address bar, similar to the one on educative.io: You'll be able to style it as per your theme.
npm
backage
Install We will use the nextjs-toploader
npm package which is fairly popular. As of this moment, it has 46k weekly downloads.
# npm
npm install nextjs-toploader
# yarn
yarn add nextjs-toploader
# pnpm
pnpm install nextjs-toploader
# bun
bun install nextjs-toploader
NextTopLoader
to your root layout.tsx
Add Go to your /app/layout.tsx
or /src/app/layout.tsx
and add the following to your root layout component's returned JSX:
import NextTopLoader from "nextjs-toploader";
export default function RootLayout() {
// component body
return (
<div>
{/* other stuff */}
{/* Add this line */}
<NextTopLoader />
</div>
);
}
Note that you do NOT need to turn your root layout into a client component with use client
to make this work. This works with server components as well.
That's it. You're done.
How to customize styling
As per the library's current npm
page, the following are the default values of the props that this component takes:
export default function RootLayout() {
// component body
return (
<div>
{/* other stuff */}
{/* Add this line */}
<NextTopLoader
color="#2299DD"
initialPosition={0.08}
crawlSpeed={200}
height={3}
crawl={true}
showSpinner={true}
easing="ease"
speed={200}
shadow="0 0 10px #2299DD,0 0 5px #2299DD"
template='<div class="bar" role="bar"><div class="peg"></div></div>
<div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'
zIndex={1600}
showAtBottom={false}
/>
</div>
);
}
showSpinner
is true
by default and shows a loading spinner on the top right corner of the screen while loading is in progress.
You can override any of these selectively, for example:
import NextTopLoader from "nextjs-toploader";
export default function RootLayout() {
// component body
return (
<div>
{/* other stuff */}
{/* Add this line */}
<NextTopLoader color="#FFFFFF" shadow={false} showSpinner={false} />
</div>
);
}