import { useEffect, useRef, useState } from "react"; /** * Hook for debounced form validation. * Validates form data after the user stops typing for a specified delay. * * @param formData - The form data to validate * @param validator - Function that validates the form data and returns field errors * @param delay - Debounce delay in milliseconds (default: 500) * @returns Object containing current errors and a function to manually trigger validation */ export function useDebouncedValidation( formData: T, validator: (data: T) => Record, delay: number = 500 ): { errors: Record; setErrors: React.Dispatch>>; validate: (data?: T) => void; } { const [errors, setErrors] = useState>({}); const validationTimeoutRef = useRef(null); const formDataRef = useRef(formData); // Keep formDataRef in sync with formData useEffect(() => { formDataRef.current = formData; }, [formData]); // Cleanup timeout on unmount useEffect(() => { return () => { if (validationTimeoutRef.current) { clearTimeout(validationTimeoutRef.current); } }; }, []); const validate = (data?: T) => { // Clear any pending validation timeout if (validationTimeoutRef.current) { clearTimeout(validationTimeoutRef.current); } // Debounce validation - wait for user to stop typing validationTimeoutRef.current = setTimeout(() => { const dataToValidate = data ?? formDataRef.current; const newErrors = validator(dataToValidate); setErrors(newErrors); }, delay); }; return { errors, setErrors, validate }; }