1
function Foo() {
  const [state, setState] = useState(0);
  const cb = useCallback(debounce(() => {
    console.log(state);
  }, 1000), []);
  return ...;
}

In this example, state can become stale in the callback. One way I can think of to fix this is something like:

function Foo() {
  const [state, setState] = useState(0);
  const cbHelper = useCallback(debounce((state2) => {
    console.log(state2);
  }, 1000), [])
  const cb = () => cbHelper(state);
  return ...;
}

However, this looks pretty messy. Is there a cleaner/better way to do this?

Edit:

I can't just do the following because debounce won't work:

useCallback(debounce(() => {
  console.log(state);
}, 1000), [state]);
Leo Jiang
  • 24,497
  • 49
  • 154
  • 284
  • It's a bit hard to recommend a different approach without more explanation of your problem. One approach that might be considered to avoid stale variables in the callback closure is by using `useRef` and keeping your state encapsulated in the ref. The ref object will only be created once, so the callback closure will have access to the same ref as the component. – Håken Lid Jun 25 '20 at 15:43
  • The use-debounce solution suggested by Fadi Quader seems to work in this way (using useRef to encapsulate the state). – Håken Lid Jun 25 '20 at 15:48
  • I recently implemented `useDebounce` and `useThrottle` with lodash helpers. If you are interested: the answer can be found [here](https://stackoverflow.com/a/62017005/5669456). – ford04 Jun 25 '20 at 16:35

1 Answers1

1

I've used use-debounce to manage that

import { useDebouncedCallback } from 'use-debounce';

function Input({ defaultValue }) {
  const [value, setValue] = useState(defaultValue);
  // Debounce callback
  const [debouncedCallback] = useDebouncedCallback(
    // function
    (value) => {
      setValue(value);
    },
    // delay in ms
    1000
  );

  // you should use `e => debouncedCallback(e.target.value)` as react works with synthetic evens
  return (
    <div>
      <input defaultValue={defaultValue} onChange={(e) => debouncedCallback(e.target.value)} />
      <p>Debounced value: {value}</p>
    </div>
  );

}

Fadi Quader
  • 143
  • 1
  • 8