"use client"; import { useState, useRef, useEffect, useCallback } from "react"; import { Range } from "react-date-range"; interface IUseDebouncedDateRangeOptions { initialDateRange?: Range[]; debounceMs?: number; onDateRangeChange?: (range: Range[]) => void | Promise; skipInitialFetch?: boolean; } export const useDebouncedDateRange = ({ initialDateRange, debounceMs = 1000, onDateRangeChange, skipInitialFetch = false, }: IUseDebouncedDateRangeOptions = {}) => { const [dateRange, setDateRange] = useState(initialDateRange ?? []); const debounceTimeoutRef = useRef(null); const isFirstMount = useRef(true); const handleDateRangeChange = useCallback( (newRange: Range[]) => { // Update state immediately for UI responsiveness setDateRange(newRange); // Clear any existing debounce timeout if (debounceTimeoutRef.current) { clearTimeout(debounceTimeoutRef.current); } // Skip fetch on first mount if requested if (isFirstMount.current) { isFirstMount.current = false; if (skipInitialFetch) { return; } } const currentRange = newRange[0]; if (!currentRange?.startDate || !currentRange?.endDate) return; // Debounce the callback debounceTimeoutRef.current = setTimeout(() => { onDateRangeChange?.(newRange); }, debounceMs); }, [onDateRangeChange, debounceMs, skipInitialFetch] ); // Cleanup timeout on unmount useEffect(() => { return () => { if (debounceTimeoutRef.current) { clearTimeout(debounceTimeoutRef.current); } }; }, []); return { dateRange, handleDateRangeChange, }; };