# useDebouncedCallback

Returns a debounced version of `callback`: it runs `delayMs` after the last call, with the arguments of that last call. The returned function is stable and always runs the latest `callback`, so it can read current state.

A pending call is dropped on unmount (call `flush` first to keep it) and when `delayMs` or `maxWaitMs` change. With `maxWaitMs`, a burst of calls still runs at least that often.

With Chinese, Japanese, or Korean input, skip calls while `e.nativeEvent.isComposing` is true and call it in `onCompositionEnd`, or it runs on half-composed text.

## Import

```ts
import { useDebouncedCallback } from '@vincent.ri/react-tils'
// or only this hook
import { useDebouncedCallback } from '@vincent.ri/react-tils/useDebouncedCallback'
```

## Usage

```ts
const search = useDebouncedCallback((query: string) => fetchResults(query), 300)
return <input onChange={(e) => search(e.target.value)} />

// Autosave while typing, at least every 5s, and save on unmount.
const save = useDebouncedCallback(saveDraft, 1000, { maxWaitMs: 5000 })
useEffect(() => () => save.flush(), [save])
```

## When to use it

Search-as-you-type requests, autosaving a draft, or validating an input after the user pauses.

## When not to

You only want to keep typing responsive while rendering something expensive; use React's `useDeferredValue`. To keep running during a burst (live results, sending positions), use `useThrottledCallback`. For scroll or resize values, prefer the dedicated hooks, which already avoid extra re-renders.

## API

```ts
function useDebouncedCallback<A extends unknown[]>(callback: (...args: A) => void, delayMs: number, options?: {
  maxWaitMs?: number;
}): DebouncedFunction<A>
```

| Parameter | Description |
| --- | --- |
| `callback` | The function to debounce. Can change every render. |
| `delayMs` | Wait this long after the last call. |
| `options` | `maxWaitMs`: run at least this often during a burst. Optional. |

**Returns** The debounced function, with `cancel`, `flush`, and `pending`.

### Types

```ts
export type DebouncedFunction<A extends unknown[]> = ((...args: A) => void) & {
  /** Drop the pending call. */
  cancel: () => void;
  /** Run the pending call now, if there is one. */
  flush: () => void;
  /** Whether a call is waiting. Reads it now; doesn't re-render when it changes, so keep state for a "Saving…" label. */
  pending: () => boolean;
};
```

## Browser support

Works in all modern browsers.

## Coming from another library?

Other libraries call this `useDebounceCallback`, `useDebounceFn`.

---

281 B minified and brotlied
Source: https://github.com/vincentri/react-tils/blob/main/src/useDebouncedCallback.ts
Docs page: https://vincentri.github.io/react-tils/hooks/useDebouncedCallback/
Previous: [useTimeout](https://vincentri.github.io/react-tils/hooks/useTimeout.md)
Next: [useDebouncedValue](https://vincentri.github.io/react-tils/hooks/useDebouncedValue.md)
