Skip to content

useDebouncedValue

Edit

Publishes the latest generic value after it remains unchanged for a delay.

useDebouncedValue.ts
import { useEffect, useState } from "react";
/** Returns the latest value after it has remained unchanged for a delay. */
export const useDebouncedValue = <Value>(
value: Value,
delayMs: number = 300,
): Value => {
if (!Number.isFinite(delayMs) || delayMs < 0) {
throw new RangeError("delayMs must be a finite, non-negative number");
}
const [debouncedValue, setDebouncedValue] = useState<Value>(() => value);
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedValue(() => value);
}, delayMs);
return () => {
clearTimeout(timer);
};
}, [delayMs, value]);
return debouncedValue;
};
Terminal
wget -O src/hooks/useDebouncedValue.ts https://raw.githubusercontent.com/jrTilak/lazykit/HEAD/registry/react-hooks/useDebouncedValue.ts
useDebouncedValue.example.tsx
import { useState } from "react";
import { useDebouncedValue } from "./useDebouncedValue";
export const SearchPreview = () => {
const [query, setQuery] = useState("");
const settledQuery = useDebouncedValue(query, 300);
return (
<label>
Search
<input
value={query}
onChange={(event) => setQuery(event.currentTarget.value)}
/>
<span>Searching for: {settledQuery || "everything"}</span>
</label>
);
};
  • value (T) — Value to publish after it settles.
  • delayMs (number, default: 300) — Finite, non-negative delay in milliseconds.

T — The initial value immediately, then the latest value whose delay completed. A value or delay change replaces the pending schedule. Function values are stored as values and are never invoked by the hook.