typescriptbeginner
useFormDirty Hook
Tracks whether a form has unsaved changes and warns before page unload.
typescriptPress ⌘/Ctrl + Shift + C to copy
import { useState, useEffect, useCallback } from 'react';
export function useFormDirty() {
const [isDirty, setIsDirty] = useState(false);
const markDirty = useCallback(() => setIsDirty(true), []);
const markClean = useCallback(() => setIsDirty(false), []);
useEffect(() => {
if (!isDirty) return;
const handler = (e: BeforeUnloadEvent) => {
e.preventDefault();
e.returnValue = '';
};
window.addEventListener('beforeunload', handler);
return () => window.removeEventListener('beforeunload', handler);
}, [isDirty]);
return { isDirty, markDirty, markClean };
}
// Usage:
// const { isDirty, markDirty, markClean } = useFormDirty();
// <input onChange={() => { handleChange(); markDirty(); }} />
// On save: markClean();Use Cases
- Form unsaved-changes warning
- Editor dirty state
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
typescriptintermediate
useFetch — Generic Data Fetching Hook
Custom React hook for data fetching with loading, error, and refetch states using the Fetch API.
Best for: API data fetching
#hooks#fetch
typescriptbeginner
useDebounce — Debounced Value Hook
Debounce any rapidly-changing value with a configurable delay. Useful for search inputs and resize handlers.
Best for: Search-as-you-type
#hooks#debounce
typescriptintermediate
useLocalStorage — Persistent State Hook
Sync React state with localStorage including SSR safety, JSON serialization, and cross-tab updates.
Best for: User preferences
#hooks#localstorage
typescriptbeginner
useClickOutside — Outside Click Detection
Detect clicks outside a referenced element to close dropdowns, modals, and popover menus.
Best for: Dropdown menus
#hooks#click-outside