Detect when the page/route is loading with custom hook - NextJS
NextJS Custom HookUpdate 2021-09-28: NextJS have updated the recommended way to detect loading since version 11. The examples have been updated. Old example can be found at the bottom of the post.
Within NextJS's router there are events that can be captured using Router from next/router.
Below is a simple custom hook that gives you a loading state boolean that you can use anywhere within your NextJS project.
TypeScript
import { useRouter } from "next/router";
import { useEffect } from "react";
import { useState } from "react";
const useLoading = (): boolean => {
const [loading, setLoading] = useState<boolean>(false);
const router = useRouter();
useEffect(() => {
const handleIsLoading = () => {
setLoading(true);
};
const handleNotLoading = () => {
setLoading(false);
};
router.events.on("routeChangeStart", handleIsLoading);
router.events.on("routeChangeComplete", handleNotLoading);
router.events.on("routeChangeError", handleNotLoading);
return () => {
router.events.off("routeChangeStart", handleIsLoading);
router.events.off("routeChangeComplete", handleNotLoading);
router.events.off("routeChangeError", handleNotLoading);
};
}, [router]);
return loading;
};
export default useLoading;
JavaScript
import { useRouter } from "next/router";
import { useEffect } from "react";
import { useState } from "react";
const useLoading = () => {
const [loading, setLoading] = useState(false);
const router = useRouter();
useEffect(() => {
const handleIsLoading = () => {
setLoading(true);
};
const handleNotLoading = () => {
setLoading(false);
};
router.events.on("routeChangeStart", handleIsLoading);
router.events.on("routeChangeComplete", handleNotLoading);
router.events.on("routeChangeError", handleNotLoading);
return () => {
router.events.off("routeChangeStart", handleIsLoading);
router.events.off("routeChangeComplete", handleNotLoading);
router.events.off("routeChangeError", handleNotLoading);
};
}, [router]);
return loading;
};
export default useLoading;
Old examples #
TypeScript
import { Router } from "next/router";
import { useState } from "react";
const useLoading = (): boolean => {
const [loading, setLoading] = useState<boolean>(false);
Router.events.on("routeChangeStart", () => {
setLoading(true);
});
Router.events.on("routeChangeComplete", () => {
setLoading(false);
});
Router.events.on("routeChangeError", () => {
setLoading(false);
});
return loading;
};
export default useLoading;
JavaScript
import { Router } from "next/router";
import { useState } from "react";
const useLoading = () => {
const [loading, setLoading] = useState(false);
Router.events.on("routeChangeStart", () => {
setLoading(true);
});
Router.events.on("routeChangeComplete", () => {
setLoading(false);
});
Router.events.on("routeChangeError", () => {
setLoading(false);
});
return loading;
};
export default useLoading;