use-debounce-pro
v1.0.1
Published
A lightweight React hook for debouncing and throttling with advanced features
Downloads
26
Maintainers
Readme
use-debounce-pro
A tiny (759B gzipped) React hook for debouncing and throttling — with full control.
Features
- ⚡ Tiny — 759 bytes gzipped, zero dependencies
- 🎯 Dual mode — Debounce and throttle in one hook
- 🔄 Edge control — Leading, trailing, or both
- ⏱️ Max wait — Guarantee execution within a time window
- 🎮 Full control —
cancel(),flush(),isPending() - 💪 TypeScript — Strict types with full generic inference
- 🌳 Tree-shakeable — ESM + CJS dual builds,
sideEffects: false - 🧹 Safe — Automatic cleanup on unmount, no stale closures
Installation
npm install use-debounce-proyarn add use-debounce-propnpm add use-debounce-proQuick Start
import { useDebouncePro } from "use-debounce-pro";
function SearchBox() {
const debouncedSearch = useDebouncePro(
(query: string) => fetchResults(query),
300,
);
return <input onChange={(e) => debouncedSearch(e.target.value)} />;
}API
useDebouncePro(callback, options)
The primary hook. Returns a debounced/throttled function with control methods attached.
const debouncedFn = useDebouncePro(callback, 300);
// or
const debouncedFn = useDebouncePro(callback, { wait: 300, leading: true });
debouncedFn("arg"); // Call the debounced function
debouncedFn.cancel(); // Cancel pending execution
debouncedFn.flush(); // Execute pending call immediately
debouncedFn.isPending(); // Check if a call is pendinguseDebouncedCallback(callback, options)
Alternative API that returns an object with named methods.
const { run, cancel, flush, isPending } = useDebouncedCallback(
(query: string) => searchAPI(query),
{ wait: 300 },
);
return <input onChange={(e) => run(e.target.value)} />;Options
| Option | Type | Default | Description |
| ---------- | -------------------------- | ------------ | ------------------------------ |
| wait | number | 0 | Delay in milliseconds |
| mode | "debounce" \| "throttle" | "debounce" | Operation mode |
| leading | boolean | false | Execute on the leading edge |
| trailing | boolean | true | Execute on the trailing edge |
| maxWait | number | undefined | Max time a call can be delayed |
When passing a number instead of an options object, it is used as the wait value with default settings.
Return Value
| Method | Type | Description |
| -------------- | -------------------------------------- | -------------------------------- |
| (…args) | (...args) => ReturnType \| undefined | The debounced function |
| .cancel() | () => void | Cancel any pending invocation |
| .flush() | () => ReturnType \| undefined | Immediately execute pending call |
| .isPending() | () => boolean | Whether a call is pending |
Common Patterns
Search Input
Debounce API calls while the user types:
function Search() {
const [results, setResults] = useState([]);
const search = useDebouncePro(async (query: string) => {
const data = await fetch(`/api/search?q=${query}`);
setResults(await data.json());
}, 300);
return <input onChange={(e) => search(e.target.value)} />;
}Scroll Handler
Throttle scroll events for performance:
function InfiniteScroll() {
const handleScroll = useDebouncePro(
() => {
const { scrollTop, scrollHeight, clientHeight } =
document.documentElement;
if (scrollTop + clientHeight >= scrollHeight - 200) {
loadMore();
}
},
{ wait: 100, leading: true, trailing: true, maxWait: 100 },
);
useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, [handleScroll]);
}Form Auto-Save
Save drafts as the user edits:
function Editor() {
const autoSave = useDebouncePro((content: string) => saveDraft(content), {
wait: 1000,
maxWait: 5000,
});
return (
<textarea
onChange={(e) => autoSave(e.target.value)}
onBlur={() => autoSave.flush()}
/>
);
}Window Resize
Recalculate layout on resize without jank:
function ResponsiveChart() {
const recalc = useDebouncePro(() => {
setDimensions({
width: window.innerWidth,
height: window.innerHeight,
});
}, 150);
useEffect(() => {
window.addEventListener("resize", recalc);
return () => window.removeEventListener("resize", recalc);
}, [recalc]);
}Comparison
| Feature | use-debounce-pro | use-debounce | lodash.debounce |
| ------------------ | :--------------: | :----------------: | :--------------: |
| Gzipped size | 759B | ~1.4KB | ~5.3KB |
| Debounce | ✅ | ✅ | ✅ |
| Throttle | ✅ | ❌ (separate hook) | ❌ (separate fn) |
| Leading/trailing | ✅ | ✅ | ✅ |
| maxWait | ✅ | ✅ | ✅ |
| cancel / flush | ✅ | ✅ | ✅ |
| isPending | ✅ | ❌ | ❌ |
| React hook | ✅ | ✅ | ❌ |
| TypeScript | ✅ (strict) | ✅ | ⚠️ @types |
| Zero dependencies | ✅ | ✅ | ❌ |
| Tree-shakeable | ✅ | ✅ | ❌ |
TypeScript
Full generic inference — your argument and return types are preserved:
// Types are inferred automatically
const debouncedSearch = useDebouncePro(
(query: string, page: number) => fetchResults(query, page),
300,
);
debouncedSearch("hello", 1); // ✅ type-safe
debouncedSearch(123); // ❌ type errorRequirements
- React ≥ 16.8.0 (hooks support)
