perform debounce in react.js

  • Last Update :
  • Techknowledgy :

Because debounced functions are stateful, we have to create one debounced function per component instance. You have to create a debounced function for each component instance, and not a single debounced function at the class level, shared by each component instance. The important part here is to create a single debounced (or throttled) function per component instance. You don't want to recreate the debounce (or throttle) function everytime, and you don't want either multiple instances to share the same debounced function.

This is our Splunktool team suggestion ✌, we tried and its working fine
//debounce with react js
// import useState hook
const [productName, setProductName] = useState("");
//write debounce function 
let timeOutId;
const handleSearch = (value)=>{
      if(timeOutId){clearTimeout(timeOutId)}
     timeOutId =  setTimeout(() => {setProductName(value)},500)
  }
//ui 
 <input type="text" onChange={(e) => handleSearch(e.target.value)} />
​

This is some initial wiring but you are composing primitive blocks on your own, and you can make your own custom hook so that you only need to do this once.

// Generic reusable hook
const useDebouncedSearch = (searchFunction) => {

   // Handle the input text state
   const [inputText, setInputText] = useState('');

   // Debounce the original search async function
   const debouncedSearchFunction = useConstant(() =>
      AwesomeDebouncePromise(searchFunction, 300)
   );

   // The async callback is run each time the text changes,
   // but as the search function is debounced, it does not
   // fire a new request on each keystroke
   const searchResults = useAsync(
      async () => {
            if (inputText.length === 0) {
               return [];
            } else {
               return debouncedSearchFunction(inputText);
            }
         },
         [debouncedSearchFunction, inputText]
   );

   // Return everything needed for the hook consumer
   return {
      inputText,
      setInputText,
      searchResults,
   };
};

And then you can use your hook:

const useSearchStarwarsHero = () => useDebouncedSearch(text => searchStarwarsHeroAsync(text))

const SearchStarwarsHeroExample = () => {
  const { inputText, setInputText, searchResults } = useSearchStarwarsHero();
  return (
    <div>
      <input value={inputText} onChange={e => setInputText(e.target.value)} />
      <div>
        {searchResults.loading && <div>...</div>}
        {searchResults.error && <div>Error: {search.error.message}</div>}
        {searchResults.result && (
          <div>
            <div>Results: {search.result.length}</div>
            <ul>
              {searchResults.result.map(hero => (
                <li key={hero.name}>{hero.name}</li>
              ))}
            </ul>
          </div>
        )}
      </div>
    </div>
  );
};

Eventually, you may add another trick if your component unmounts:

componentWillUnmount() {
   this.setState = () => {};
}

ES6 (class property): recommended

class SearchBox extends React.Component {
   method = debounce(() => {
      ...
   });
}

Suggestion : 2

A Debouncing Events in ReactJS will allow you to call a function that ensures that a time-consuming task does not fire so often. It’s a function that takes a function as a parameter and wraps that function in a closure and returns it so this new function displays the “wait for a bit” behavior. Step 3: After creating the ReactJS application, Install the required module using the following command: Step 2: After creating your project folder i.e. react-debouncing, move to it using the following command:

Creating React Application And Installing Module:

Step 1: Create a React application using the following command:

npx create - react - app react - debouncing
2._
cd react - debouncing

 

npm install lodash

Step to Run Application: Run the application using the following command from the root directory of the project:

npm start

Suggestion : 3

First of all, create a state using the useState hook in React. We will also need to destroy the instance of the useEffect hook using return, followed by clearTimeout, every time it finishes. Now, we need to set the data in the pinCode state when we type something, using the onChange event handler. The input character is getting passed to the function as an argument and we are passing the value as path parameters. We are also logging the response in the console.

In the below example, we are simply calling an API using the axios.get method when we type any numeric character in the input box.

The input character is getting passed to the function as an argument and we are passing the value as path parameters. We are also logging the response in the console.

import axios from "axios";
import React from "react";
import "./styles.css";

export default function App() {
  const setInput = (value) => {
    axios
      .get(`https://api.postalpincode.in/pincode/${value}`)
      .then((response) => {
        console.log(response.data[0]?.PostOffice[0]);
      });
  };
  return (
    <div className="app">
      <input
        placeholder="Search Input.."
        onChange={(e) => setInput(e.target.value)}
      />
    </div>
  );
}

Now, let's change the whole flow in order to add debouncing. In the case of Debouncing, the API will trigger only once after 2 seconds, after we type our whole pin-code.

const [pinCode, setPinCode] = React.useState("");
3._
<input
      placeholder="Search Input.."
      onChange={(event) => setPinCode(event.target.value)}
 />

In this useEffect Hook, we will have a function called getData. This function getData will have a callback function called setTimeOut. And we will set the timer for 2 seconds.

React.useEffect(() => {
   const getData = setTimeout(() => {

   }, 2000)
}, [pinCode])

And now in this getData function, let's call our API.

React.useEffect(() => {
   const getData = setTimeout(() => {
      axios
         .get(`https://api.postalpincode.in/pincode/${pinCode}`)
         .then((response) => {
            console.log(response.data[0]);
         });
   }, 2000)
}, [pinCode])

Suggestion : 4

You have 2 options to create debounced and throttled functions in React: using useCallback() or useMemo() hooks. That's not a problem regarding the correctness: useCallback() makes sure to return the same debounced function instance. But it would be wise to avoid calling debounce(...) on each rendering. Otherwise, when the handlers are invoked too often you risk making the application lagging or even unresponsive for a few seconds. Fortunately, debouncing and throttling techniques can help you control the invocation of the event handlers.

Let's say that a component <FilterList> accepts a big list of names (at least 200 records). The component has an input field where the user types a query and the names are filtered by that query.

Here's the first version of <FilterList> component:

jsximport { useState } from 'react';export function FilterList({ names }) {  const [query, setQuery] = useState('');  let filteredNames = names;  if (query !== "") {    filteredNames = names.filter((name) => {      return name.toLowerCase().includes(query.toLowerCase());    });  }  const changeHandler = event => {    setQuery(event.target.value);  };  return (    <div>      <input         onChange={changeHandler}         type="text"         placeholder="Type a query..."      />      {filteredNames.map(name => <div key={name}>{name}</div>)}    </div>  );}

To debounce the changeHandler function I'm going to use the lodash.debounce package. You can use any other library at your will, or even write the debounce function by yourself.

First, let's look at how to use the debounce() function:

javascriptimport debounce from 'lodash.debounce';
const debouncedCallback = debounce(callback, waitTime);

The only problem with applying debouncing to changeHandler inside a React component is that the debounced version of the function should remain the same between component re-renderings.

The first approach would be to use the useCallback(callback, dependencies) that would keep one instance of the debounced function between component re-renderings.

jsximport { useState, useCallback } from 'react';import debounce from 'lodash.debounce';export function FilterList({ names }) {  const [query, setQuery] = useState("");  let filteredNames = names;  if (query !== "") {    filteredNames = names.filter((name) => {      return name.toLowerCase().includes(query.toLowerCase());    });  }  const changeHandler = event => {    setQuery(event.target.value);  };  const debouncedChangeHandler = useCallback(    debounce(changeHandler, 300)  , []);  return (    <div>      <input         onChange={debouncedChangeHandler}         type="text"         placeholder="Type a query..."      />      {filteredNames.map(name => <div key={name}>{name}</div>)}    </div>  );}

If the debounced handler uses props or state, to avoid creating stale closures, I recommend setting up correctly the dependencies of useMemo():

jsximport {
   useMemo
}
from 'react';
import debounce from 'lodash.debounce';

function MyComponent({
   prop
}) {
   const [value, setValue] = useState('');
   const eventHandler = () => { // the event uses `prop` and `value`  };  const debouncedEventHandler = useMemo(    () => debounce(eventHandler, 300)  , [prop, stateValue]);    // ...}

The debounce and throttle implementations usually provide a special method to cancel the execution. For example lodash.debounce library provides debouncedCallback.cancel() to cancel any scheduled calls.

Here's how you can cancel the debounced function when the component unmounts:

jsximport {
   useState,
   useMemo,
   useEffect
}
from 'react';
import debounce from 'lodash.debounce';
export function FilterList({
   names
}) { // ....  const debouncedChangeHandler = useMemo(    () => debounce(changeHandler, 300)  , []);  // Stop the invocation of the debounced function  // after unmounting  useEffect(() => {    return () => {      debouncedChangeHandler.cancel();    }  }, []);  return (    // ....  );}

Suggestion : 5

The package comes with a DebounceInput component that we can use in place of the <input /> tag. It has an inbuilt debounce functionality, so we won’t need any external debounce method to debounce our onChange event. Now that we are using the <DebounceInput /> component, we can go back to the simple version of the doCityFilter() function: There’s an even easier way to implement input debouncing in React. Let’s learn how to use the react-debounce-input package to solve our city filter problem.

So instead of asking our computer to filter through a list of over 70,000 data 13 times, it does that just once.

In JavaScript, the setTimeout() method is a perfect candidate for implementing this solution. Here’s what our component looks like at the moment:

import cities from 'cities-list'
import { useState } from 'react'

const citiesArray = Object.keys(cities)

const App = () => {
  const [filteredCities, setFilteredCities] = useState([])

  const doCityFilter = query => {
    if (!query) return setFilteredCities([])

    setFilteredCities(citiesArray.filter(
      city => city.toLowerCase().includes(query.toLowerCase())
    ))
  }

  return (
    <div className="container">
      <h1>Find your favourite cities</h1>

      <form className="mt-3 mb-5">
        <input
          type="text"
          className="px-2"
          placeholder="search here..."
          onChange={event => (doCityFilter(event.target.value))}
        />
      </form>

      <div>
        {filteredCities?.map((city, index) => (
          <p key={index}>{city}</p>
        ))}
      </div>
    </div>
  )
}

export default App

Since the filter process is happening inside the setFilteredCities function call, let’s use the setTimeout method to delay it by 500ms:

const doCityFilter = query => {
   if (!query) return setFilteredCities([])

   setTimeout(() => {
      console.log('====>', query)
      setFilteredCities(citiesArray.filter(
         city => city.toLowerCase().includes(query.toLowerCase())
      ))
   }, 500)
}

While this delays our function, notice that we have another problem. Our filter method is still being called for each of the keystrokes — again, that’s 16 times in total. We only ended up delaying each of the 16 calls by 500ms. What we want is to cancel the previous setTimeout method whenever we hit a new key, so that if we have 16 keystrokes, we’ll end up calling the filter function for just the last key. Let’s use the cleartimeout method to implement this:

let filterTimeout

const doCityFilter = query => {
   clearTimeout(filterTimeout)
   if (!query) return setFilteredCities([])

   filterTimeout = setTimeout(() => {
      console.log('====>', query)
      setFilteredCities(citiesArray.filter(
         city => city.toLowerCase().includes(query.toLowerCase())
      ))
   }, 500)
}

Next, we’ll import it in our App.js file. Let’s do that on line 3.

...
import debounce from 'lodash.debounce'

Our first instinct might be to debounce the setFilteredCities function call like we did with our setTimeout implementation:

const doCityFilter = query => {
   if (!query) return setFilteredCities([])

   const debouncedFilter = debounce(() => {
      console.log('====>', query)
      setFilteredCities(citiesArray.filter(
         city => city.toLowerCase().includes(query.toLowerCase())
      ))
   }, 500)

   debouncedFilter()
}

Suggestion : 6

React component that renders an Input, Textarea or other element with debounced onChange. Can be used as drop-in replacement for <input type="text" /> or <textarea /> Value of the Input box. Can be omitted, so component works as usual non-controlled input. This package has only been tested with <input /> and <textarea /> but should work with any element which has value and onChange props. Function called when value is changed (debounced) with original event passed through

1._
npm install--save react - debounce - input
2._
yarn add react - debounce - input
3._
<script src="https://unpkg.com/react@16.0.0/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-debounce-input/build/react-debounce-input.js"></script>
(Module exposed as `DebounceInput`)
5._
<DebounceInput element="textarea" />
6._
<textarea />

Suggestion : 7

Debouncing in Javascript is an effective method for enhancing browser performance. It is time-consuming computations so that they could invoke or degrade frequently. The programming practice Debouncing based on Debouncing is a suitable option for maintaining the time-consuming tasks. Usually, the process is a convenient option for limiting the rate of invoked functions during the progression. Creating the short backend program using node assures you the better string. Get the best react js development services suitable for Performing the Debounce in Reactjs and save more time. For Debouncing the changeHandler function in Reactjs, it is convenient to use lodash. Debounce package. These are mainly enabled with various libraries that allow debouncing action.

Step 1: Create a React application using the following command:

npx create - react - app react - debouncing

Step 2:After creating your project folder, i.e. react-debouncing, move to it using the following command:

cd react - debouncing

Step 3: After creating the ReactJS application, Install the required module using the following command:

npm install lodash

These are mainly enabled with the frequent server API changes so that they degrade the server performance. Various applications based on debouncing are available such as content-loading WebPages such as Face, Twitter, and many more. These applications mainly allow users to keep the content and scroll it down continuously.

Usually, when the scrolled event is clicked frequently, it could create an impact. The main reason is that they contain more images and videos. Scroll events make use of debouncing. For example, when you are looking for debounce handleOnChange

function debounce(fn, delay) {
  var timer = null;
  return function() {
    var context = this,
      args = arguments;   
clearTimeout(timer);
    timer = setTimeout(function() {     
fn.apply(context, args);
    }, delay);
  };
}
var SearchBox = React.createClass({
  render: function() {
    return <input type="search" name="p" onChange={this.handleOnChange} />;
  }, 
handleOnChange: function(event) {
    // make ajax call
  }
});
6._
import debounce from 'lodash.debounce';
const debouncedCallback = debounce(callback, waitTime);