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

Author: marcebdevCreated Nov 13, 2024Updated Oct 22, 2025
Labelsbug

Describe the bug

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

Using a custom arrow function like you'd use in 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 (it is not a useCallback variant hook without this fix)

To Reproduce

typescript
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