Skip to content

Instantly share code, notes, and snippets.

@ngbrown
Last active August 19, 2023 17:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ngbrown/e0aa1efd61263a40e52d2f3d9d1ce0b4 to your computer and use it in GitHub Desktop.
Save ngbrown/e0aa1efd61263a40e52d2f3d9d1ce0b4 to your computer and use it in GitHub Desktop.
useDynamicThrottle React hook
import { useCallback, useEffect, useRef, useState } from "react";
/**
* Returns a throttled version of the value and a function to release the next update, which may occur immediately or
* on the next value change.
*
* This can be used to keep the interface responsive when you have values that are changing too fast for async processes to keep up.
* @param value The value that is going to be throttled
*/
export function useDynamicThrottle<T>(
value: T
): [throttledValue: T, releaseNextValue: () => void] {
const valueRef = useRef(value);
// true if updated values need to be held until releaseNext is called; false otherwise.
const holdingRef = useRef(true);
const [throttledValue, setThrottledValue] = useState(value);
const releaseNextValue = useCallback(() => {
const current = valueRef.current;
setThrottledValue((prev) => {
if (!Object.is(prev, current)) {
holdingRef.current = true;
return current;
} else {
holdingRef.current = false;
return prev;
}
});
}, []);
useEffect(() => {
valueRef.current = value;
if (!holdingRef.current) {
holdingRef.current = true;
releaseNextValue();
}
}, [releaseNextValue, value]);
return [throttledValue, releaseNextValue];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment