Dirty state / unsaved-changes guard

The app knows you have edits you never saved, so it warns you before you navigate away and lose them.

are you sure you want to leavedon't lose my workunsaved changes warningunsaved changes gaurdleave site? changes you made may not be savedbeforeunload promptwarn before closing the tabdirty form check

See it

Live demo coming soon

What it is

Two pieces wearing one name. Dirty state is the flag that says the current values differ from the last saved snapshot. The guard is the interception that fires when a dirty user tries to leave: a browser 'Leave site?' dialog on tab close, or your own modal on an in-app route change.

Reach for it on anything with real typing behind it: long forms, editors, settings panels, anywhere a stray back-button press costs someone ten minutes. The browser half is the 'beforeunload' event; the in-app half needs a router blocker (React Router 'useBlocker', Next.js route-change interception), because client-side navigation never unloads the page and 'beforeunload' will not save you.

Gotcha: you do not get to write the browser dialog. Custom text was killed off years ago, so every site shows the same generic warning. The bigger trap is a sloppy dirty check. If autofill, a trimmed string, or a reformatted phone number marks the form dirty when nothing meaningful changed, users get warned for nothing and learn to click through the warning that actually matters.

Ask AI for it

Add an unsaved-changes guard to this form. Keep a snapshot of the last saved values and derive a 'dirty' boolean by comparing current values against it (normalize whitespace and formatting first so cosmetic differences do not count). While dirty, register a 'beforeunload' handler for tab close or reload, and block in-app navigation with a router blocker that opens a modal offering 'Save and leave', 'Discard changes', and 'Keep editing'. Clear the dirty flag and unregister both guards immediately after a successful save.

You might have meant

autosave with save indicatordestructive action confirmationstate persistenceerror preventionescape hatch

Go deeper