import * as React from 'react'; import useLatest from '@digigov/ui/utils/hooks/useLatest'; export const useDebounceCallback = ( callback: (...args: CallbackArgs) => void, wait = 100, leading = false ): ((...args: CallbackArgs) => void) => { const storedCallback = useLatest(callback); const timeout = React.useRef>(undefined); const deps = [wait, leading, storedCallback]; // Cleans up pending timeouts when the deps change React.useEffect( () => () => { if (timeout.current) clearTimeout(timeout.current); timeout.current = void 0; }, deps ); return React.useCallback(function () { // eslint-disable-next-line prefer-rest-params const args = arguments; const { current } = timeout; // Calls on leading edge if (current === void 0 && leading) { timeout.current = setTimeout(() => { timeout.current = void 0; }, wait); return storedCallback.current.apply(null, args as any); } // Clear the timeout every call and start waiting again if (current) clearTimeout(current); // Waits for `wait` before invoking the callback timeout.current = setTimeout(() => { timeout.current = void 0; storedCallback.current.apply(null, args as any); }, wait); }, deps); }; export const useDebounce = ( initialState: State | (() => State), wait?: number, leading?: boolean ): [State, React.Dispatch>] => { const state = React.useState(initialState); return [state[0], useDebounceCallback(state[1], wait, leading)]; };