A debounce is a tool that every web developer should have in their kit. It improves performance by limiting the number of expensive calculations, API calls, and DOM updates. Although the debounce technique has been around for years, it’s still a great option to employ with modern libraries and frameworks. At gitconnected we use it with React and Redux to keep the application blazing fast.

We’ll define a <Project> component that creates a list for all projects. It’s wired up to a mockApi() to simulate the need to do an API call. I’ve put everything inside the single file instead of connecting it Redux, but all the principles still apply to whatever state management and API framework you have set up. I’ve numbered the typical bottlenecks 1–3 in the code.

We have a simple <ul> that lists projects by name, and an <input> that allows us to filter these projects. When there is an onKeyUp triggered on the <input> it executes the handleFilter() which is wrapped in our debounce function. This limits our mockApi() function to only be called every 500ms. By debouncing, we remove the need to perform these operations every key press, and we only do it after the user has stopped typing for a short amount of time. This ensures that we don’t perform unnecessary operations to find projects the user didn’t even care to see. Let’s take a look at the individual steps to understand how much we actually saved.

After the debounce time expires after the final key press, the first step is to make our API call. Since we have debounced the function that fetches from our API, we only make the request once at the end of typing into the input. There are two things happening here — retrieving projects from the database and then performing heavy calculations to filter and sort the data. In a practical context, the server would be more efficient about querying and performing calculations on this data, but the learning outcome is still completely valid. In this instance, let’s assume we type 5 characters within our debounce timer. Without the debounce, we would perform 5 queries of 1 billion items and then perform the filtering, string matching, and sorting. Thus we’ve gained a 5x performance improvement on a what is already an incredibly heavy computationally intensive action. React is fast, but the biggest thing that can slow it down is too many renders and reconciliations. In addition, DOM interaction are incredibly slow. By debouncing, we prevent the setState() which serves to significantly reduce the number of times we force React to reconcile and append the list to the DOM.

Without a debounce, this component would be almost unusable with such a large amount of data. This concept is easily extended to Redux for any state updates or API calls. If these interactions dispatched other actions, we are once again achieving a multiplicative gain.