-1

I have a problem about debounce in Function Component ReactJS.

Code here:

let timeout;
const App = () => {
  const [value, setValue] = useState("");
  const func = () => {
    console.log("value: ", value);
  };

  const debounce = (func, wait) => {
    if (timeout) clearTimeout(timeout);
    timeout = setTimeout(() => {
      func();
    }, wait);
  };

  const onChange = event => {
    const { value: v } = event.target;
    setValue(v);
    debounce(func, 3000);
  };

  return (
    <>
      <Input
        value={value}
        name="value"
        onChange={onChange}
        placeholder="Basic usage"
      />
    </>
  );
};

Why when I press "123" then result of debounce function is: "12"

san
  • 1,515
  • 11
  • 18
  • State updates are async, so the last debounce queued up has the current state `"12"` before the update occurs. – Drew Reese May 19 '20 at 07:49

1 Answers1

0

When setValue sets the state, the result is reflected in the next render and not immediately after calling setValue due to closure.

Check this post for more details related to it: useState set method not reflecting change immediately

However you must also note that you must not declare a global timeout variable since it will restrict you to use only one instance of your class

You can write the above code in the following manner to avoid closure and instance issues

const App = () => {
  const [value, setValue] = useState("");
  const timeout = useRef(null);
  const func = (val) => {
    console.log("value: ", val);
  };

  const debounce = (func, wait) => {
    if (timeout.current) clearTimeout(timeout.current);
    timeout.current = setTimeout(() => {
      func();
    }, wait);
  };

  const onChange = event => {
    const { value: v } = event.target;
    setValue(v);
    debounce(() => func(v), 3000);
  };

  return (
    <>
      <Input
        value={value}
        name="value"
        onChange={onChange}
        placeholder="Basic usage"
      />
    </>
  );
};
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400