useDebounce
Delay value until after a specified delay period to optimize performance and reduce API calls.
useDebounce
Delay value updates until after a specified delay period to optimize performance and reduce unnecessary API calls.
Installation
npx open-hook add useDebounceyarn dlx open-hook add useDebouncepnpm dlx open-hook add useDebounceAPI Reference
Parameters
| Prop | Type | Default |
|---|---|---|
options? | number | DebounceOptions | 500 |
value? | T | - |
DebounceOptions
| Prop | Type | Default |
|---|---|---|
maxWait? | number | - |
trailing? | boolean | true |
leading? | boolean | false |
unit? | TimeUnit | 'ms' |
delay? | number | - |
Returns
| Prop | Type | Default |
|---|---|---|
debouncedValue? | T | - |
TypeScript Signature
type TimeUnit = "ms" | "s" | "min";
interface DebounceOptions {
delay: number;
unit?: TimeUnit;
leading?: boolean;
trailing?: boolean;
maxWait?: number;
}
function useDebounce<T>(value: T, options?: number | DebounceOptions): T;Advanced Usage Examples
// Basic usage with milliseconds
const debouncedValue = useDebounce(searchTerm, 300);// Using different time units
const debouncedValue = useDebounce(value, {
delay: 1,
unit: "s", // 1 second
});
const debouncedValue2 = useDebounce(value, {
delay: 2,
unit: "min", // 2 minutes
});// Trigger immediately on first change
const debouncedValue = useDebounce(searchTerm, {
delay: 300,
leading: true, // Immediate first trigger
trailing: true, // Also trigger after delay
});// Force update after maximum wait time
const debouncedValue = useDebounce(value, {
delay: 500,
maxWait: 2000, // Force update after 2 seconds max
});Best Practices
Choose appropriate delay values and configurations based on your use case:
// Search input - fast feedback with leading edge
const debouncedSearch = useDebounce(searchTerm, {
delay: 300,
leading: true,
trailing: true,
});
// Form validation - moderate delay, trailing only
const debouncedInput = useDebounce(inputValue, {
delay: 500,
trailing: true,
});
// Auto-save with maximum wait time
const debouncedData = useDebounce(formData, {
delay: 800,
maxWait: 5000, // Force save after 5 seconds
});Advanced Features
- 🚀 Time Units: Use seconds or minutes for longer delays instead of calculating milliseconds
- ⚡ Leading Edge: Get immediate feedback on first interaction
- ⏱️ Max Wait: Ensure updates don't get delayed indefinitely
- 🎯 Trailing Edge: Standard debounce behavior (default)
Do's and Don'ts
- ✅ Use leading edge for immediate user feedback
- ✅ Set maxWait for auto-save functionality
- ✅ Choose appropriate time units for readability
- ✅ Use simple number for basic debouncing
- ❌ Don't use excessively long delays (>5min)
- ❌ Avoid both leading and trailing false
- ❌ Don't use complex configs for simple cases
Performance Metrics
| Metric | Value | Description |
|---|---|---|
| Bundle Size | ~0.6kb | Minified + gzipped |
| API Calls Reduced | Up to 90% | Fewer unnecessary requests |
| Memory | Minimal | Single timer per instance |
| CPU Impact | Very Low | Simple setTimeout operation |
Browser Compatibility
| Browser | Supported | Notes |
|---|---|---|
| Chrome (latest) | ✅Yes | Full support |
| Firefox (latest) | ✅Yes | Full support |
| Safari (latest) | ✅Yes | Full support |
| Edge (latest) | ✅Yes | Full support |
| IE 11 | ❌No | Not supported |
| Node.js | ✅Yes | For SSR environments |
Use Cases
Search Functionality
Delay search API calls until the user stops typing to improve performance.
Auto-save Features
Automatically save form data after the user pauses editing.
Form Validation
Delay expensive validation checks until input stabilizes.
Filter Operations
Reduce heavy filtering operations on large datasets.
Accessibility
Accessibility Considerations
- The hook doesn't affect accessibility directly - Ensure loading states are communicated to screen readers - Consider providing immediate feedback for user interactions - Use appropriate ARIA labels for search inputs using debounced values
Troubleshooting
Internals
How It Works
The hook maintains an internal state for the debounced value and uses setTimeout to delay updates. Each time the input value changes, it clears the previous timer and sets a new one. Only when the timer completes without interruption does it update the debounced value.
This pattern effectively "debounces" rapid changes, ensuring that expensive operations (like API calls) only happen after the user has stopped providing input for the specified delay period.
Testing Example
import { renderHook, act } from "@testing-library/react";
import { useDebounce } from "./useDebounce";
jest.useFakeTimers();
it("debounces value updates", () => {
const { result, rerender } = renderHook(
({ value, delay }) => useDebounce(value, delay),
{ initialProps: { value: "initial", delay: 500 } }
);
expect(result.current).toBe("initial");
// Update value
rerender({ value: "updated", delay: 500 });
expect(result.current).toBe("initial"); // Still old value
// Fast forward time
act(() => {
jest.advanceTimersByTime(500);
});
expect(result.current).toBe("updated"); // Now updated
});FAQ
Related Hooks
- useThrottle - Limit execution frequency instead of delaying
- useAsyncState - Handle async operations with loading states
- useLocalStorage - Persist debounced values locally
Changelog
- 2.0.0 — Major release with advanced features
- Added support for multiple time units (ms, s, min)
- Implemented leading edge execution option
- Added trailing edge configuration
- Introduced maxWait option for forced updates
- Enhanced TypeScript support with DebounceOptions interface
- Breaking: Changed API to accept options object
- Improved memory management with proper cleanup
- 1.2.0 — Added TypeScript generics and improved performance
- 1.1.0 — Added configurable delay parameter
- 1.0.0 — Initial release with basic debounce functionality