Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React use debounce with setState

Background

Assume we all know about the debounce function from lodash.

If a user quickly input 1,12,123,1234, it allows us to proceed an alert only once, with 1234, after a certain delay time.

This is quite used to reduce request amount, for optimization.


Description

For a normal input field, we can use that kind of debounce and it works.

Problem: Once we add a setState inside the same callback with debounce, the debounce won't work as normal.

Does anyone know the reason?

import React, { useState } from "react";
import "./styles.css";
import { debounce } from "lodash";

export default function App() {
  const [input, setInput] = useState("");

  const debouceRequest = debounce(value => {
    alert(`request: ${value}`);
  }, 1000);
  const onChange = e => {
    setInput(e.target.value); // Remove this line will lead to normal debounce
    debouceRequest(e.target.value);
  };

  return (
    <div className="App">
      <input onChange={onChange} />
    </div>
  );
}

Edit flamboyant-field-equct

like image 439
keikai Avatar asked Mar 21 '20 14:03

keikai


People also ask

How do you use debounce in Reactjs?

In the case of Debouncing, the API will trigger only once after 2 seconds, after we type our whole pin-code. First of all, create a state using the useState hook in React. const [pinCode, setPinCode] = React. useState("");

How do I debounce a callback?

Debouncing a callback, the first attempt You can use any other library at your will, or even write the debounce function by yourself. import debounce from 'lodash. debounce'; const debouncedCallback = debounce(callback, waitTime);

What is the difference between Debounce and throttle?

Throttle: the original function will be called at most once per specified period. Debounce: the original function will be called after the caller stops calling the decorated function after a specified period.


1 Answers

Try this (using useCallback):

import React, { useState, useCallback } from "react";
import "./styles.css";
import { debounce } from "lodash";

const request = debounce(value => {
  alert(`request: ${value}`);
}, 1000);

export default function App() {
  const [input, setInput] = useState("");

  const debouceRequest = useCallback(value => request(value), []);

  const onChange = e => {
    debouceRequest(e.target.value);
    setInput(e.target.value); // Remove this line will lead to normal denounce
  };

  return (
    <div className="App">
      <input onChange={onChange} />
    </div>
  );
}

Edit elated-dawn-lb5ex

like image 178
Ehsan Avatar answered Sep 20 '22 10:09

Ehsan