All files / src/hooks useFormDirtyState.ts

81.81% Statements 9/11
100% Branches 2/2
75% Functions 3/4
80% Lines 8/10

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37                                8x   8x 8x   4x           4x   4x 4x       8x    
import { useEffect } from "react";
 
/**
 * Hook to track if form values have changed from their initial state.
 * Performs deep comparison via JSON.stringify and registers a beforeunload
 * event to warn users about unsaved changes when closing the browser tab.
 *
 * @param currentValues - Current form state values
 * @param initialValues - Initial form state values (snapshot from props)
 * @returns isDirty - True if current values differ from initial values
 */
export function useFormDirtyState(
	currentValues: Record<string, unknown>,
	initialValues: Record<string, unknown>,
): boolean {
	const isDirty =
		JSON.stringify(currentValues) !== JSON.stringify(initialValues);
 
	useEffect(() => {
		if (!isDirty) return;
 
		const handleBeforeUnload = (e: BeforeUnloadEvent) => {
			e.preventDefault();
			// Modern browsers ignore the custom message but still show a warning
			e.returnValue = "";
		};
 
		window.addEventListener("beforeunload", handleBeforeUnload);
 
		return () => {
			window.removeEventListener("beforeunload", handleBeforeUnload);
		};
	}, [isDirty]);
 
	return isDirty;
}