Skip to content

Instantly share code, notes, and snippets.

@olpeh
Last active May 10, 2021 06:51
Show Gist options
  • Save olpeh/88cacf89d221800395654e7a7ee9f9e3 to your computer and use it in GitHub Desktop.
Save olpeh/88cacf89d221800395654e7a7ee9f9e3 to your computer and use it in GitHub Desktop.
Loading indicator between pages during navigation in Next.js – one option
import React, { useEffect, useState } from "react";
import { useRouter } from "next/router";
import type { AppProps } from "next/app";
const App = ({ Component, pageProps }: AppProps) => {
const router = useRouter();
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
const handleRouteChangeStart = () => {
setIsLoading(true);
// Can be possibly removed after Next.js fixes this:
// https://github.com/zeit/next.js/issues/7681
document.body.setAttribute("tabIndex", "-1");
};
const handleRouteChangeComplete = () => {
setIsLoading(false);
document.body.focus();
};
const handleBlur = () => {
document.body.removeAttribute("tabIndex");
};
document.body.addEventListener("blur", handleBlur);
router.events.on("routeChangeStart", handleRouteChangeStart);
router.events.on("routeChangeComplete", handleRouteChangeComplete);
router.events.on("routeChangeError", handleRouteChangeComplete);
return function cleanup() {
router.events.off("routeChangeStart", handleRouteChangeStart);
router.events.off("routeChangeComplete", handleRouteChangeComplete);
router.events.off("routeChangeError", handleRouteChangeComplete);
document.body.removeEventListener("blur", handleBlur);
};
}, [router.asPath, router.events]);
return (
<>
<header>...</header>
<main>
{isLoading ? <LoadingIndicator /> : <Component {...pageProps} />}
</main>
<footer>...</footer>
</>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment