import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; export function useServerDraft(server: T | undefined, clone: (value: T) => T, equals: (left: T, right: T) => boolean) { const cloneRef = useRef(clone); const equalsRef = useRef(equals); cloneRef.current = clone; equalsRef.current = equals; const [draft, setDraft] = useState(); const [baseline, setBaseline] = useState(); const draftRef = useRef(draft); const baselineRef = useRef(baseline); draftRef.current = draft; baselineRef.current = baseline; useEffect(() => { if (server === undefined) return; const currentDraft = draftRef.current; const currentBaseline = baselineRef.current; const isDirty = currentDraft !== undefined && (currentBaseline === undefined || !equalsRef.current(currentDraft, currentBaseline)); setBaseline(server); if (isDirty && !equalsRef.current(currentDraft, server)) return; setDraft(cloneRef.current(server)); }, [server]); const markSaved = useCallback((value: T) => { setBaseline(cloneRef.current(value)); }, []); const isDirty = useMemo( () => draft !== undefined && (baseline === undefined || !equalsRef.current(draft, baseline)), [baseline, draft], ); return { draft, setDraft, isDirty, markSaved }; }