Easy Event Throttling in React

Sometimes we need to limit the number of times a function is called. This is especially useful for events that are fired multiple times and that result in expensive operations like making an asynchronous call to the backend, re-rendering the screen or loading remote content. In this short tutorial, we will create a search bar that retrieves results only once every 200 milliseconds. We will be using only React and Lodash.

What is Debouce?

Debouncing: To limit a function to be called only once in a period of time.

This is very simple to implement with lodash which already has an implementation:

const myFunction = () => console.log('Hello!');
const myDebouncedFunction =  var debounced = _.debounce(myFunction, 500);

In this example, myFunction will be called only once every 500 milliseconds.

Problem with React Async Events

In modern React versions, events are pooled by the SyntheticEvent. That means that the same event object is reused again and again to improve performance. By default, every time a new event is fired, it overwrites the previous event. The problem with this approach is that if you need to access the event properties at a later time, they will not be available.

By default, every time a new event is fired, it overwrites the previous event.

A poor solution would be to use the event.persist() to disable event pooling because it affects performance. Let’s take a look at another way:


Debouncing Input Events in React

The majority of the time all we need from an event is just the target value, so it is not necessary to keep the entire event. The trick consists in having two functions, one that is the event handler which is synchronous, and another function which the debounced one. In the first function, we extract the desired values from the event, and with those values, we then can call the debounced function.

Note that if we try calling an async or debounced function with the event, then the event will not be available, because when it runs the event pool probably cleared the event already.

In the following example, we will have an input that is used for searching.

import _ from 'lodash';
import React, { Component } from 'react';

class Search extends Component {
  constructor(props) {

    this.onChange = this.onChange.bind(this); // binding this because onChange is called in another scope
    this.debouncedOnChange = _.debounce(this.debouncedOnChange.bind(this), 200); // debouncing function to 200ms and binding this

  onChange(event) {
    this.debouncedOnChange(event.target.value); // sending only the values not the entire event

  debouncedOnChange(value) {
    this.search(value); // perform a search only once every 200ms

  search(value) {
    // fetch objects from backend

  render() {
    return (
        <input onChange={this.onChange} />

export default Search;

We listen to the onChange event but, we don’t want to kick off the async call to the server every time a single key is pressed. So we will throttle this call to only 1 call every 200 milliseconds. Pay special attention to the binding of this as both functions are called from another scope.


Throttling and debouncing function calls in React with Lodash is a simple and useful technique that can improve the performance of both the front-end and the back-end without sacrificing user experience. Experiment with different times to finetune to your application. I’ve found that values between 100ms-300ms often work great.

I hope this short tutorial was helpful to you!

Additional Solutions

There are a few React packages for throttling and debouncing functions and components including react-throttle and react-debounce-input . I haven’t personally used them, but they seem useful for certain cases. For me, I prefer to keep things minimal and have the least amount of dependencies.

Share Post :

1 Comment

  • YX cHEN
    January 10, 2020 at 10:17 pm 

    Thanks for your sharing. It is worked in my example. But there is some question when I use this way to listen to the event Scroll, the Event is still triggered over and over again. What a pity.

Leave a Reply