Table of contents
Debouncing is a technique that helps in limiting the frequency of function calls. It is commonly used to introduce a delay in executing functions following user-triggered events like clicks, input changes, mouseover and mouseout actions, form submissions, and more.
Let's say we have a database table containing a list of books that we want to query based on the book's name via an API endpoint so we can suggest books that match the user's query. The API call may look like this:
const searchBooks = (query) => {
fetch(`https://booklovers.com/books?query=${query}`)
.then(res => res.json())
.catch(err => console.log(err))
}
This function, if resolved, returns an array of books that match the query parameter.
We would also have an input element that grabs the user's search query and runs the searchBooks()
function every single time there's a change in input value.
<!-- index.html -->
<input type="search" onChange={e => searchBooks(e.target.value) } >
While a user is typing into the search box, the searchBooks()
function is called over and over again, for every single letter entered. This is counterproductive as it wastes resources and can cause performance issues.
A better way of doing this will be by using debouncing. Debouncing is a way of saying "wait until this amount of time before calling this function". In our case, it lets us get more data, in terms of search query letters, from the user to help fine-tune the results. For instance, a query of "harry" is more likely to return more tailored data than "ha" and we only have to make one API call.
Implementation
A very simple implementation would be to only call the searchBooks()
function 3 seconds after the user has made a change to the search query.
const debounceSearch = (query) => {
let timer;
// clears previous timer
clearTimeout(timer);
timer = setTimeout(
() => {
searchBooks(query);
}, 3000)
};
clearTimeout: cancels the timer if there has been another change to the search query
setTimeout: schedules the searchBooks()
function to be executed after 3000ms i.e. 3seconds.
Now, our app should be able to call the searchBooks()
function and send an API request only after 3 seconds after a pause in user activity, clear the timer function and set a new one if there is a resumption of that activity.
This is how our app should appear now:
import { useState } from 'react';
export default function App() {
const [value, setValue] = useState('');
const searchBooks = (query) => {
setValue(query);
// run api call here
};
const debounceSearch = (query) => {
let timer;
clearTimeout(timer);
timer = setTimeout(() => {
searchBooks(query);
}, 3000);
}
return (
<div className="App">
<h1>My Library</h1>
<input type="search" onChange={e => debounceSearch(e.target.value) } />
{/* will show search query only after 3 seconds */}
<p>{value}</p>
</div>
);
};
You can view the app here.
Other Applications
Other applications of debouncing include:
Form input validation: Debouncing can be used to delay validating a user's input until after the user is done typing.
Infinite scroll: You can load more content as a user scrolls down instead of trying to load all the content at once or triggering the load function more frequently than needed.
Delaying API Calls After User Interactions: API calls can be delayed until after the user is done interacting with a UI component.
Preventing Duplicate API Requests: It prevents duplicate API calls if there's a possibility of continuously performing an event in quick succession e.g. clicking on a submit button.
Delaying User Feedback: Debouncing is useful in creating a more user-friendly experience by ensuring a feedback message is not displayed immediately.
Benefits
Here are the benefits of debouncing:
Reduced API calls
Reduced function calls
Improved browser performance
Optimized resource usage
May prevent unwanted side effects caused by rapid triggers
Smoother and more responsive user experience
Control over event handling
Conclusion
Debouncing is a great technique for gaining greater control over event handling in your application, allowing you optimize browser performance and resource usage while ensuring a smoother user experience.
In this article, I have shown you how to implement a debounce function. However, there are libraries that provide abstraction so you don't have to write it from scratch yourself. Some of these include: react-debounce-input and lodash.
Happy Coding!๐