client_side_routing.js 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. import { useEffect, useRef, useState } from "react";
  2. import { useRouter } from "next/router";
  3. /**
  4. * React hook for use in /404 page to enable client-side routing.
  5. *
  6. * Uses the next/router to redirect to the provided URL when loading
  7. * the 404 page (for example as a fallback in static hosting situations).
  8. *
  9. * @returns {boolean} routeNotFound - true if the current route is an actual 404
  10. */
  11. export const useClientSideRouting = () => {
  12. const [routeNotFound, setRouteNotFound] = useState(false);
  13. const didRedirect = useRef(false);
  14. const router = useRouter();
  15. useEffect(() => {
  16. if (
  17. router.isReady &&
  18. !didRedirect.current // have not tried redirecting yet
  19. ) {
  20. didRedirect.current = true; // never redirect twice to avoid "Hard Navigate" error
  21. // attempt to redirect to the route in the browser address bar once
  22. router
  23. .replace({
  24. pathname: window.location.pathname,
  25. query: window.location.search.slice(1),
  26. })
  27. .then(() => {
  28. // Check if the current route is /404
  29. if (router.pathname === "/404") {
  30. setRouteNotFound(true); // Mark as an actual 404
  31. }
  32. })
  33. .catch((e) => {
  34. setRouteNotFound(true); // navigation failed, so this is a real 404
  35. });
  36. }
  37. }, [router.isReady]);
  38. // Return the reactive bool, to avoid flashing 404 page until we know for sure
  39. // the route is not found.
  40. return routeNotFound;
  41. };