0

I am trying to implement debounce on search.
The idea is to send a request to the api once user stopped typing.
I have a working example, which works fine. You can see there that typed value will be printed on the screen once finished typing
Now I am trying to implement the same feature on the same input with search functionality, but it doesn't work and throws an error:

TypeError: Cannot read properties of null (reading 'value')

Here is the component and the sandbox link

import React, { useState } from "react";
import data from "./MOCK_DATA.json";
function App() {
  const [name, setName] = useState("");
  const debounce = (func, delay) => {
    let timer;
    return (...arg) => {
      if (timer) clearTimeout(timer);
      timer = setTimeout(() => {
        func(...arg);
      }, delay);
    };
  };

  const onChangeHandler = (e) => {
    setName(e.target.value);
  };

  const debouncedOnChangeHandler = debounce(onChangeHandler, 1000);

  const filteredData = data.filter((el) =>
    el.first_name.toLowerCase().includes(name.toLowerCase())
  );
  return (
    <div>
      <div style={{ width: "100%" }}>Search</div>
      <input
        value={name}
        onChange={debouncedOnChangeHandler} //debouncedOnChangeHandler doesn't work because value is asynchronous
        //onChange={onChangeHandler} //this works fine without debounce function
        type="text"
        placeholder="search"
      />
      {filteredData &&
        filteredData.map((el) => <div key={el.id}>{el.first_name}</div>)}
    </div>
  );
}

export default App;

Any help will be appreciated.

FD3
  • 1,462
  • 6
  • 24
  • 47
  • Instead of implementing it on your own, I recommend using `useDebounce` from the `react-use` package: https://github.com/streamich/react-use/blob/master/docs/useDebounce.md – marcobiedermann Aug 22 '22 at 11:53
  • @marcobiedermann thanks for the advice. I appreciate it. But before moving to packages, I want to understand how it works and the use them. – FD3 Aug 22 '22 at 11:56
  • 1
    @Greg, Check this https://codesandbox.io/s/mutable-mountain-ec3q9j . Make the debounce handler like `const debouncedOnChangeHandler = debounce(onChangeHandler, 1000);` and remove `value={name}` in the input. – Maniraj Murugan Aug 22 '22 at 12:15
  • @ManirajMurugan wait what did you change? It works fine – FD3 Aug 22 '22 at 12:19
  • @ManirajMurugan ok I see, you removed value field – FD3 Aug 22 '22 at 12:20
  • @ManirajMurugan can you explain please, why it was not working and why it started to work after removing value from input? – FD3 Aug 22 '22 at 12:21
  • Also could you post your answer so that I can mark as a correct answer? – FD3 Aug 22 '22 at 12:23
  • @Greg, Posted as answer and you need to make two changes here as described below. – Maniraj Murugan Aug 22 '22 at 12:50
  • Does this answer your question? [How to perform debounce?](https://stackoverflow.com/questions/23123138/how-to-perform-debounce) – Emile Bergeron Aug 22 '22 at 17:56

1 Answers1

3

There are some changes which you need to make,

First debouncedOnChangeHandler variable holds the function like,

   const debouncedOnChangeHandler = (e) => {
    debounce(onChangeHandler(e), 1000);
   };

But whereas this doesn't pass the onChangeHandler as expected argument for debounce method.

So you need to just passdown the debounce function along with required parameters like,

const debouncedOnChangeHandler = debounce(onChangeHandler, 1000);

Second: You need to remove value={name} which is not needed in this context.

Forked Codesanbox:

Edit mutable-mountain-ec3q9j

Maniraj Murugan
  • 8,868
  • 20
  • 67
  • 116