April 4, 2024
When interacting with a web application, we might fire bursting events such as entering text in a search field, resizing a window, scrolling, or dragging an element on the screen. These events are repeatedly invoked, which significantly decreases the website's performance by making it laggy, and sometimes unresponsive. To handle such situations, debouncing comes to the rescue.
Debouncing is a programming technique that limits the call to a function or an event. Debounced functions only run after a specified period and not when they are invoked.
There are many ways to achieve debouncing in JavaScript. We are going to implement it in the following ways.
We start by creating a function that returns another function. This function handles all the logic of calling the function passed as a parameter when the specified time is passed.
const debounce = (func, delay) => {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => {
clearTimeout(timer);
func(...args);
}, delay);
};
};The function defined above is a higher-order function that accepts a function as an argument and returns a function. With this, we create a closure around the func, delay and the timer variable so they can preserve the value when the parent function is executed and removed from the call stack.
Another way we can achieve debouncing is to use a library called lodash. We can make use of the debounce method which is provided by lodash.
npm install lodash
import { debounce } from "lodash"We simply need to wrap the callback function with the debounce method and provide the delay as a second parameter.
const handleValueChange = debounce(( value ) => {
setValue( value );
}, 500);We can make our own implementation of debouncing using a custom hook. We would use
We can use npm or yarn to install the packages.
npm install awesome-debounce-promise react-async-hook use-constantImport the packages into react application
import useConstant from "use-constant";
import { useAsync } from "react-async-hook";
import AwesomeDebouncePromise from "debounce-promise";We are making use of use-constant package as this aids us in executing the function once and store the returned value in a constant.
import { useState } from "react";
import useConstant from "use-constant";
import { useAsync } from "react-async-hook";
import AwesomeDebouncePromise from "debounce-promise";
const useDebounce = (func, delay) => {
const [text, setText] = useState("");
const debouncedSearchFunction = useConstant(() =>
AwesomeDebouncePromise(func, delay)
);
const searchResults = useAsync(async () => {
if (text.length === 0) {
return [];
} else {
return debouncedSearchFunction(text);
}
}, [debouncedSearchFunction, text]);
return {
text,
setText,
searchResults
};
};
export default useDebounce;Let’s dive deep into the code.
useConstant hook is called, which accepts a function as a parameter. useConstant helps in executing this function only once. We can use React’s useMemo but it won’t guarantee that the function is only called once.AwesomeDebouncePromise which debounces async calls. This method accepts a function which is to be debounced, and a timer which indicates the time after which the function is invoked.useAsync along with debouncedSearchFunction and text in the dependency array. Every time the text changes, it calls the callback function, but as it is debounced, it is not invoked frequently.text, setText, and searchResults from the hook.Let’s move on to app.js where are going to use the hook we just implemented.
import React, { useState } from "react";
import useDebounce from "./useDebounce";
const App = () => {
const [value, setValue] = useState("");
const { text, setText } = useDebounce(
(text) => handleValueChange(text),
1000
);
const handleValueChange = (value) => {
setValue(value);
};
return (
<>
Using custom hook for debouncing
setText(e.target.value)}
/>
You entered: {value}
>
);
};
export default App;useDebounce hook. This hook returns text, setText, and searchResults which are destructured.onChange is fired where we pass e.target.value to setText.We have seen how we can implement debouncing using three different techniques. We start with simple implementation from scratch, followed by debouncing with lodash, and finally writing our custom hook.
If you have any queries, let me know in the comment section.
Happy coding !!!