Skip to content

Instantly share code, notes, and snippets.

@Spidy88
Last active May 28, 2025 23:17
Show Gist options
  • Save Spidy88/9fe9c464d1e170e2c83ab23bfa3f4342 to your computer and use it in GitHub Desktop.
Save Spidy88/9fe9c464d1e170e2c83ab23bfa3f4342 to your computer and use it in GitHub Desktop.
React Hook - useDebounce
import debounce from 'lodash/debounce';
import noop from 'lodash/noop';
import { useState, useCallback, useRef } from 'react';
interface UseDebounceOptions<T> {
initialValue: T;
onChange?: (value: T) => void;
debounceTime?: number;
}
const useDebounce = <T>({
initialValue,
onChange = noop,
debounceTime = 500,
}: UseDebounceOptions<T>) => {
const [realTimeValue, setRealTimeValue] = useState<T>(initialValue);
const [debouncedValue, setDebouncedValue] = useState<T>(initialValue);
// We track onChange in a ref because debounce needs a stable function reference
// (thus useCallback), but if the user does not give us a stable callback, we
// must invoke the most recent version when debounce fires (thus the ref)
const onChangeRef = useRef(onChange);
onChangeRef.current = onChange;
// eslint-disable-next-line react-hooks/exhaustive-deps
const handleDebounce = useCallback(
debounce((value: T) => {
setDebouncedValue(value);
onChangeRef.current(value);
}, debounceTime),
[],
);
const setValue = (value: T) => {
setRealTimeValue(value);
handleDebounce(value);
};
const setValueImmediately = (value: T) => {
setRealTimeValue(value);
setDebouncedValue(value);
onChange(value);
// Make sure we queue up this value on the debounce in case another one is in-flight
handleDebounce(value);
};
return {
realTimeValue,
debouncedValue,
setValue,
setValueImmediately,
};
};
export default useDebounce;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment