A super basic boilerplate wrapping Next.js route abort events
useUnsavedChangesWarning(form.isDirty === true && status !== 'pending')| import { useEffect } from "react"; | |
| import { useRouter } from "next/router"; | |
| export function useUnsavedChangesWarning(hasUnsavedChanges: boolean) { | |
| const router = useRouter(); | |
| useEffect(() => { | |
| const handleRouteChangeStart = (url: string) => { | |
| if (hasUnsavedChanges && router.asPath !== url) { | |
| const confirmed = confirm( | |
| "You have unsaved changes that will be lost. Are you sure you want to leave?", | |
| ); | |
| if (!confirmed) { | |
| router.events.emit("routeChangeError"); | |
| throw "Route change aborted by user"; | |
| } | |
| } | |
| }; | |
| const handleBeforeUnload = (event: BeforeUnloadEvent) => { | |
| if (hasUnsavedChanges) { | |
| event.preventDefault(); | |
| event.returnValue = "You have unsaved changes that will be lost."; | |
| } | |
| }; | |
| if (hasUnsavedChanges) { | |
| router.events.on("routeChangeStart", handleRouteChangeStart); | |
| window.addEventListener("beforeunload", handleBeforeUnload); | |
| } | |
| return () => { | |
| router.events.off("routeChangeStart", handleRouteChangeStart); | |
| window.removeEventListener("beforeunload", handleBeforeUnload); | |
| }; | |
| }, [hasUnsavedChanges, router]); | |
| } |