Debounce in JavaScript

Kay Bennett
2 min readNov 12, 2018

Debounce is a great tool to have at your disposal when optimising your React application’s performance. We often want to manipulate the DOM based on user events, and we want our applications to be fast and responsive. Often, events happen in bursts — a user types a word or phrase, or resizes the window.

Take a look at the code snippets below from a simple React application. We have a simple search input, which filters a list of Pokémon based on the user’s input. The filter is stored in the state of the PokemonIndex component.

updateFilter = (input) => {                           this.setState({ filter: input })                           
let { pokemons } = this.state
return pokemons.filter(pokemon => pokemon.name.includes(this.state.filter) )}
...<Search onKeyUp={(e) => this.updateFilter(e.target.value), 500)} showNoResults={false} />

This code works, but the issue here is that our event listener is firing every single time our user presses a key (‘onKeyUp’), and so we are firing the ‘updateFilter’ function on each and every keystroke. This is a little excessive and could lead to noticeably laggy performance on slower browsers. Enter ‘debounce’.

Debounce is intended to be used with fast-changing values. It comes in handy when we want to change what our user sees based on an event, but we don’t want our function to run an unnecessarily high number of times. Debounce delays function execution until the user has stopped responding for a set length of time — on a onKeyUp listener, it will pause until a user has stopped typing, on a window resize listener, it will pause until the user has stopped resizing the page. This is particularly useful when we are carrying out more expensive operations.

Debounce is not a native feature of Javascript. It comes with a number of popular Javascript libraries like Lodash and Underscore.js. They all use the native setTimeout function. Using Lodash’s debounce, we can refactor the above to:

<Search onSearchChange={_.debounce((e, input) => this.updateFilter(input.value), 500)} showNoResults={false} />

Check out the Lodash documentation on debounce for more information about how debounce works under the hood.

--

--