Execute a function after a timeout every time your data changes. Reset the timer if the data changes again during the timeout.
Sometimes when the user updates some state, we want to make an API request to sync the state remotely. We cannot run a function every time the user changes the data however.
What we do instead is debounce the state update, i.e. waiting a fixed amount of time after the user stops interacting before making the request. Furthermore, we want to reset the timeout if in the meantime the user changes the state again.
Well, that's what useDebounceUpdate
is made for!
isFirstRender
is used to avoid running execute
at first render (which is probably something that you don't want here 💁🏼♂️).
Every time data
changes timer
resets and the execute
function will be called again only after timeout
milliseconds.
import { useEffect, useRef } from "react";
/**
* Run the `execute` function after `timeout` milliseconds.
* If the value of `data` changes, reset the timer.
*/
export const useDebounceUpdate = <Data>({
execute,
data,
timeout = 2000,
}: {
data: Data;
timeout?: number;
execute: (value: Data) => void;
}): void => {
const isFirstRender = useRef(true);
const timer = useRef<ReturnType<typeof setTimeout>>();
useEffect(() => {
if (!isFirstRender.current) {
if (timer.current) {
clearTimeout(timer.current);
}
timer.current = setTimeout(() => {
execute(data);
}, timeout);
} else {
isFirstRender.current = false;
}
}, [data]);
};