juliencrn / usehooks-ts

React hook library, ready to use, written in Typescript.
https://usehooks-ts.com
MIT License
6.57k stars 424 forks source link

[BUG] useDebounceCallback doesn't seem to memoize the callback function #656

Open marcebdev opened 1 week ago

marcebdev commented 1 week ago

Describe the bug

Debounce is called multiple times if you use a non-memoized function like an inline arrow function or something like you'd typically put into a useCallback (so not passing a setState` or something directly).

Using a custom arrow function like you'd use useCallback or something similar is not uncommon nor unresonable. Many other libraries show better examples (than passing a useState directly) and use something like this as an example e.g. https://mantine.dev/hooks/use-debounced-callback/

So the issues are many fold:

  1. a stronger example is needed, as we can see useState is basically cheating
  2. improve tests as critical test cases are missed
  3. fix bug

To Reproduce

const Test = () => {
  const [value, setValue] = useState<string>('')
  const [, setDebouncedValue] = useState('')

  const debounce = useDebounceCallback((val: string) => {
    console.log('debounced', val)
    if (value) setDebouncedValue(val)
  }, 1500)

  return (
    <input
      value={value}
      onChange={({ target: { value } }) => {
        setValue(value)
        debounce(value)
      }}
    />
  )
}

Expected behavior

debounced functions should be called once

Right now that console will print the following if "123" is typed

debounced 1 debounced 12 debounced 123

Additional context

No response

marcebdev commented 6 days ago

I don't mean to be bitter or rude and can def appreciate the contributions to this library, but given such a critical/misdocumented issue with this hook and seeing other debounce hook related issues I think I'll step away from this library.

FWIW this library has one of my fav set of functions but if they don't work reliably it's hard to rely on them