Optimizing User experience is one of the key elements in Web Development. One aspect of improving the user experience is debouncing
What is debouncing?
Debouncing in simple terms is just delaying a function to make sure that it doesn’t get called too often which can lead to performance issues. You might wanna ask, why’d we want to delay the function?
Nice Question!
The answer is what if the function uses heavy resources in our software? We cannot afford it to get called too often. For example, if the function is calling an API we wouldn’t wanna call it too many times.
Real world Example
Suppose we are creating a live search features where whenever user types the name of a product, the list updates in real-time. Now, let’s suppose for every key stroke that user makes an API is getting called.
Suppose the user is searching for MacBook Air
. In this case 11 subsequent API requests (for each character) will be made to the server, which can increase server load and cause performance issues.
Solution
The Solution is debouncing the function. Which means that we will add a delay to the function to make sure the user has finished typing. And if the user types again we will just cancel the previous call and call the function again when the user finishes.
In this tutorial we’re gonna create a useDebounce() hook for this purpose.
export function useDebounce<T>(value: T, delay?: number): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value);
useEffect(() => {
const timer = setTimeout(() => setDebouncedValue(value), delay || 500);
return () => {
clearTimeout(timer);
};
}, [value, delay]);
return debouncedValue;
}
Now, let's dive deeper into the live search example we've discussed earlier. As mentioned before, the hook will update the value of debouncedValue
state every delay
milliseconds. This means that every time the user types a character, the hook waits for delay
milliseconds before updating the debouncedValue
. If during that duration the value passed is changed, the previous timeout is cleared and a new timeout is set. This ensures that the hook only returns the final value after the user has stopped typing for at least delay
milliseconds. Once the timeout is over, the debouncedValue
is changed to the final value. This way, we can avoid unnecessary API calls or other expensive operations that would slow down the user interface.
Usage of the hook
export default function Component() {
const [value, setValue] = useState<string>("");
const debouncedValue = useDebounce<string>(value, 500);
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setValue(event.target.value);
};
// Fetch API (optional)
useEffect(() => {
// Do fetch here...
// Triggers when "debouncedValue" changes
}, [debouncedValue]);
return (
<div>
<p>Value real-time: {value}</p>
<p>Debounced value: {debouncedValue}</p>
<input type="text" value={value} onChange={handleChange} />
</div>
);
}
Resources
https://usehooks-ts.com/react-hook/use-debounce
Conclusion
I hope you enjoyed this tutorial. If you think I made a mistake somewhere let me know in the comment section.
My Socials
Twitter - https://twitter.com/shaancodes
Instagram - https://www.instagram.com/shaancodes/
GitHub - https://github.com/shaan-alam/