Search code examples
javascriptreactjsdebouncing

React JS: Debounce


Consider the below React code. Here I am trying to add the debounce functionality when there is an input change. It's working as expected i.e. when there is a delay of 3000ms then also API call takes place. But the issue is, Suppose let's say I entered 4 characters, then after 3000ms, 4 different API calls are taking place instead of 1. Why is this happening, anything wrong with what I am doing? When I remove the below-mentioned line, the issue solves. Why is that?

const [inputValue, setInputValue] = useState("");

const getSearch = (val) => {

    axios.get("url")
         .then(({ data }) => {      
         }).catch( () => {
         })
}    

const holdSearch = (callback, delay) => {
    let clear;
    return function(...args) {
       clearTimeout(clear);
       clear = setTimeout(() => {
                   callback(args[0]);
               }, delay);
    }
 }

const makeSearch = holdSearch(getSearch, 3000);

const handleChange = ({target}) => {
       
   setInputValue(target.value); // If I remove this statement, everything works as required
   makeSearch(target.value);

}

HTML tag

<input value = {inputValue} onChange = {handleChange} />

Solution

  • Each time the component renders you create a new makeSearch function. There's nothing necessarily bad about that, except that it also mean you have a brand new clear variable. So calling clearTimeout(clear) never does anything, because clear is always a brand new variable with a value of undefined

    You need the value to stick around from one render to another, which means using useRef:

    const timerId = useRef();
    const holdSearch = (callback, delay) => {
      return function (...args) {
        clearTimeout(timerId.current);
        timerId.current = setTimeout(() => {
          callback(args[0]);
        }, delay);
      }
    }
    

    When I remove the below-mentioned line, the issue solves. Why is that?

    If you don't set state, then the component doesn't rerender, so there are no new variables created. Any onChangeEvents that happen later will go to the same handleChange function and the same makeSearch function.

    That's not something you want to depend on though. Your component should be written so if it rerenders it will still work, as in my suggestion above