import { useCallback, useEffect, useRef, useState } from "react"; /** * Easy way to debounce the handling of a rapidly changing value, e.g. a changing slider input * @param value value that is rapidly changing * @param onChange change handler that should receive the debounced updates to the value * @param debouncedMs how long we should wait for changes to be applied */ export default function useDebouncedChangeHandler( value: T, onChange: (newValue: T) => void, debouncedMs = 100 ): [T, (value: T) => void] { const [inner, setInner] = useState(() => value); const timer = useRef>(); const onChangeInner = useCallback( (newValue: T) => { setInner(newValue); if (timer.current) { clearTimeout(timer.current); } timer.current = setTimeout(() => { onChange(newValue); timer.current = undefined; }, debouncedMs); }, [debouncedMs, onChange] ); useEffect(() => { if (timer.current) { clearTimeout(timer.current); timer.current = undefined; } setInner(value); }, [value]); return [inner, onChangeInner]; }