Effects
useDebounceValue
State whose debounced copy updates after a pause.
Demo
live · imported from hookli
- live
- —
- debounced
- —
settled
import { useState } from "react";
import { useDebounceValue } from "hookli";
export function Demo() {
const [text, setText] = useState("");
const [debounced, setValue] = useDebounceValue("", 500);
return (
<div>
<input
value={text}
onChange={(e) => {
setText(e.target.value);
setValue(e.target.value);
}}
/>
<p>Debounced: {debounced}</p>
</div>
);
}Usage
import { useState } from "react";
import { useDebounceValue } from "hookli";
export function Demo() {
const [text, setText] = useState("");
const [debounced, setValue] = useDebounceValue("", 500);
return (
<div>
<input
value={text}
onChange={(e) => {
setText(e.target.value);
setValue(e.target.value);
}}
/>
<p>Debounced: {debounced}</p>
</div>
);
}API
useDebounceValue<T>(initialValue: T | (() => T), delayMs?: number, options?: DebounceOptions & { equalityFn?: (left: T, right: T) => boolean }): [T, DebouncedState<[T | ((prev: T) => T)], void>]Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| initialValue | T | (() => T) | — | The starting value, or a factory evaluated once on mount — the same lazy-initializer contract as useState. |
| delayMs | number | 500 | Milliseconds of inactivity before the debounced value catches up to the latest set value. |
| options | DebounceOptions & { equalityFn? } | {} | DebounceOptions plus an optional equalityFn (left, right) => boolean — when it reports the values equal, the debounced update is skipped. See the tables below. |
Returns
| Name | Type | Description |
|---|---|---|
| [0] debouncedValue | T | The value that trails the setter, updating only after delayMs of quiet. |
| [1] setValue | DebouncedState<[T | ((prev: T) => T)], void> | A debounced setter accepting a value or updater; it also carries cancel, flush and isPending (see DebouncedState). |
DebounceOptions
Controls how the debounced invocation is scheduled.
| Name | Type | Description |
|---|---|---|
| leading | boolean | Invoke on the leading edge — run once immediately on the first call of a burst. |
| trailing | boolean | Invoke on the trailing edge — run after the burst settles. |
| maxWait | number | The maximum time the callback may be delayed before it is forced to run, even during a continuous burst. |
DebouncedState<Args, R>
The debounced function, plus manual control methods.
| Name | Type | Description |
|---|---|---|
| (...args) | (...args: Args) => R | undefined | Calling it schedules an invocation and returns the last computed result — undefined before the first run. |
| cancel | () => void | Cancels any pending trailing invocation. |
| flush | () => R | undefined | Immediately runs any pending invocation and returns its result. |
| isPending | () => boolean | Whether a trailing invocation is currently scheduled. |
Hook
The implementation, straight from hookli. Copy it, or install the package.
import { useEffect, useRef, useState } from "react";
import {
useDebounceCallback,
type DebounceOptions,
type DebouncedState,
} from "../use-debounce-callback/use-debounce-callback";
export type UseDebounceValueReturn<T> = [
T,
DebouncedState<[value: T | ((prev: T) => T)], void>,
];
export const useDebounceValue = <T>(
initialValue: T | (() => T),
delayMs = 500,
options: DebounceOptions & { equalityFn?: (left: T, right: T) => boolean } = {},
): UseDebounceValueReturn<T> => {
const eq = options.equalityFn ?? ((left, right) => left === right);
const unwrap = (v: T | (() => T)): T =>
typeof v === "function" ? (v as () => T)() : v;
const [debouncedValue, setDebouncedValue] = useState<T>(() =>
unwrap(initialValue),
);
const previousValue = useRef(debouncedValue);
const updateDebouncedValue = useDebounceCallback(
(value: T | ((prev: T) => T)) => {
const next =
typeof value === "function"
? (value as (prev: T) => T)(previousValue.current)
: value;
if (!eq(previousValue.current, next)) {
previousValue.current = next;
setDebouncedValue(next);
}
},
delayMs,
options,
);
useEffect(() => {
return () => updateDebouncedValue.cancel();
}, [updateDebouncedValue]);
return [debouncedValue, updateDebouncedValue];
};