Debounce lets us make multiple calls to a function and only run that function after a delay from when the last call was made.

In React apps this is useful when the user can trigger an event several times in quick succession and it would be expensive to run a function call on every event, such as when we want to have some functionality after a user pauses typing into an input box or after a user stops scrolling.

There are many libraries that come with a debounce function which we can use (such as lodash), but to better understand debounce writing our own rudimentary version can be helpful.

Debounce with Class Components

Now let’s add it to a simple search input built in React. We’ll start with how we would do it with a class based component. What we would like to do is console.log what our searchText is but only after our user finishes typing. Here is our component without the debounce:

And here is how we add debounce.

Debounce with Functional Components

Now let’s write debouncedLog in a functional component. With functional components it’s a little trickier, if we just try and port it directly over it won’t work.

The problem is that unlike class methods which get defined once, functions inside of functional components get redefined every time the component re-renders. For many functions this doesn’t matter, but for our debouncedFunction all of our private variables are getting reset every time! What we need to do is memoize the definition of debouncedLog and not redefine it later. React has multiple hooks that let us do exactly this, the most idiomatic of which is useCallback.

Debouncing Values

Another option we have to get the desired debounced effect is instead of making a debounced function we debounce the value itself. Then we perform our console.log whenever the debouncedValue updates with useEffect.

And here is what our useDebounce might look like