React Js: Debouncing or delaying value change using custom hook

Karthik Raja
2 min readMay 2, 2021

--

Debouncing is a method by which we can delay the execution of a function by some time. The simplest example is a search function that has to call an API based on the value entered by the user. In React it is done usually in this way:

const [value, setValue] = useState('');useEffect(()=> {
callSomeApi(value);
},[value]);
<input value={value} onChange={(e) => setValue(e.targe.value)} />

The main problem with this approach is that the API will be called for every keyPress event. This can greatly affect the overall performance and even raise security issues in the backend.

The easiest solution here will be allowing the user to first complete typing her/his search term and then make the API call. How do we know the user has completed typing? Well, we’ll have to wait till the typing stops.

So, keeping this requirement in mind let's build a custom hook called useDebounce.

The useDebounce hook

The hook will use useState and useEffect internally to achieve the required delay and return the value and setter function, just like the useState hook.

Notice the return array — We are returning the debounce value and the setter function of the actual value. This will ensure that the hook can be used just like the useState hook.

The next step is to set debounceValue, which actually will be same as actualValue, just set after the delay.

Looks clean right? Well, no. There’s a catch here. You can see the useEffect will be called whenever the actualValue changes, which is actually what we want. But, the setTimeout function will also be called every time, which will get stacked in the event queue and get executed one by one, ultimately changing debounceValue for every keypress event.

To fix this, we simply clear the interval for every keypress event. Meaning, the debounceValue will not be updated until the user stops typing. And once the user stops typing, there will be just one setTimeout function waiting in the event queue to get executed after the specified delay.

Mission accomplished!

This is the final code. Now, this hook can be used like the useState hook, just with the delay parameter.

const [value, setValue] = useDebounce('',1000);useEffect(()=> {
callSomeApi(value);
},[value]);
<input value={value} onChange={(e) => setValue(e.targe.value)} />

Thanks!

--

--