shadcn.io is an independent project built on shadcn/ui
useDebounceValue holds the latest value until updates pause for the delay you pass.
The first argument is the value to follow, or a function that returns it. To delay a function instead of a value, use useDebounceCallback. A React search field can show each key at once and send the query after the pause.
Installation
Anatomy

Usage
import { useDebounceValue } from "@/hooks/use-debounce-value";const [value, setValue] = useDebounceValue(text, 500);
setValue(next);
setValue.cancel();
setValue.flush();FAQ
When should I use useDebounceValue instead of useDebounceCallback?
useDebounceValue returns the settled value plus a setter with cancel, flush, and isPending. useDebounceCallback returns a delayed function. Choose the value hook when other render logic should read the quiet value. Choose the callback when you only need to postpone work. The value hook still schedules through lodash, with the same leading, trailing, and maxWait options.
What does equalityFn change?
equalityFn decides whether a new incoming value counts as a change. The default is strict equality, so left === right. Return true to skip the debounced write. The comparison runs during render, and only a difference calls the setter. For objects, compare the fields you care about. Keep the options object stable, because a new one on each render rebuilds the debounced setter.
How do I apply or drop a waiting update?
Call flush on the setter to run a waiting update immediately. Call cancel to drop it, so the stored value stays where it is. flush returns the result of that update, or undefined when nothing was waiting. The state setter itself returns void. These methods are on the setter, not on the value. Unmount does not cancel the setter you were given.
Can the first argument be a function?
Yes, and it is called on every render. The return value is what the hook compares and stores. This is not a one-time initializer the way useState treats a function. The first render stores that result immediately. Later renders schedule an update only when equalityFn says it changed. If the value you want to store is itself a function, this hook will call it.
What does isPending report?
isPending on the setter does not track a lodash timer. After the first effect it returns true, because that effect saves a debounced function on a ref and the check is only that the ref is set. Before the effect it returns false. It stays true when no update is waiting. Use cancel to drop a pending write, and read the returned value to see what is committed.
When does a new value get scheduled?
The hook compares the incoming value during render, not inside an effect. When equality fails, it calls the debounced setter in that render. With the default trailing behavior, lodash only schedules the state write for later. With leading set to true, lodash can run that write during render, which makes React warn. The committed value usually changes on a later render, after the delay.
API Reference
Parameters
initialValueT | (() => T)
The value to follow (or a function that returns the first one). Each change schedules an update.
- Type
T | (() => T)
delaynumber
Milliseconds to wait after the last change.
options?UseDebounceValueOptions<T>
Debounce timing, and how two values compare.
- Type
UseDebounceValueOptions<T>
options.leading?boolean
Also calls at the start of a burst, not only once it settles.
- Default
false
options.maxWait?number
The longest it may wait, in milliseconds, before calling anyway.
options.trailing?boolean
Calls once the burst settles, with the last arguments.
- Default
true
options.equalityFn?(left: T, right: T) => boolean
Whether a new value is the same as the last one, so no update is scheduled. === when left out.
- Type
(left: T, right: T) => boolean
Returns
[0] debouncedValueT
The value, updated delay milliseconds after it last changed.
[1] updateDebouncedValueDebouncedState<(value: T) => void>
Sets the value, debounced, with cancel, flush and isPending.
- Type
DebouncedState<(value: T) => void>
updateDebouncedValue(…)(...args: Parameters<T>) => ReturnType<T> | undefined
Sets the value once calls stop for delay milliseconds.
- Type
(...args: Parameters<T>) => ReturnType<T> | undefined
updateDebouncedValue.cancel() => void
Drops the call that's waiting.
- Type
() => void
updateDebouncedValue.flush() => void
Runs the call that's waiting now, instead of after the delay.
- Type
() => void
updateDebouncedValue.isPending() => boolean
true once the debounced function is set up (from the first render on): it doesn't track whether a call is waiting.
- Type
() => boolean











