Skip to content

useThrottledCallback

Watches an array of dependencies executed a callback at a given delay every time the dependency array changes.

Installation

npx rabbithook@latest add use-throttled-callback

Usage

App.tsx
import useThrottledCallback from "@/hooks/use-throttled-callback";
function Component() {
const [state, setState] = useState("");
useThrottledCallback(() => {
console.log("changed!")
}, 2 * 1000 /* 2 seconds */, [state]);
return (
<>
<p>State: {state}</p>
<input value={state} onChange={event => setState(event.target.value)} />
</>
);
}

If you want to pass in data to this callback function, you can execute the function returned by the hook and pass in the data to it. When the callback runs, the data provided to the returned function will be passed to the callback.

App.tsx
import useThrottledCallback from "@/hooks/use-throttled-callback";
function Component() {
const [state, setState] = useState("");
const setCallbackParameters = useThrottledCallback((value: string) => {
console.log(`Changed! Now the value is: ${value}`)
}, 2 * 1000, [state]);
function handleChange(value: string) {
setState(value);
setCallbackParameters(value);
}
return (
<>
<p>State: {state}</p>
<input value={state} onChange={event => handleChange(event.target.value)} />
</>
);
}

Code

use-throttled-value.ts
/* eslint-disable react-hooks/exhaustive-deps */
import { useEffect, useRef } from 'react';
function useThrottledCallback<T>(cb: (params?: T) => void, delay: number, dependencyArray: unknown[]): (params: T) => void {
const lastExecutedRef = useRef(0);
const cbRef = useRef(cb);
const paramsRef = useRef<T>();
useEffect(() => {
const now = Date.now();
const timeSinceLastExecution = now - lastExecutedRef.current;
if (timeSinceLastExecution >= delay) {
cbRef.current(paramsRef.current);
lastExecutedRef.current = now;
} else {
const timeoutId = setTimeout(() => {
cbRef.current(paramsRef.current);
lastExecutedRef.current = Date.now();
}, delay - timeSinceLastExecution);
return () => clearTimeout(timeoutId);
}
}, [...dependencyArray, delay]);
function setThrottledCallbackParams(params: T) {
paramsRef.current = params;
}
return setThrottledCallbackParams;
}
export default useThrottledCallback;