About
A hook that returns a debounced version of the provided value. The debounced value will only update after the specified delay has passed without any new changes to the original value.
Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds useDebounce to your project and fits it to your theme.
Code
How useDebounce is used: the demo's code. The component's own source comes with a free account.
Usage.tsx
"use client";
import { useState, useEffect } from 'react';
import { useDebounce } from '@/components/hooks/use-debounce';
import { Input } from "@/components/ui/input";
// Simple Input Demo
export function DebounceInputDemo() {
const [inputValue, setInputValue] = useState('');
const debouncedValue = useDebounce(inputValue, 500);
const [apiResult, setApiResult] = useState('');
useEffect(() => {
// Имитация API запроса
if (debouncedValue) {
setApiResult(`Making API call with: ${debouncedValue}`);
}
}, [debouncedValue]);
return (
<div className="flex flex-col gap-4 w-[300px]">
<div className="space-y-2">
<p className="text-sm text-muted-foreground">
Type something to see debounce in action
</p>
<Input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="Start typing..."
/>
</div>
<div className="space-y-2">
<p className="text-sm font-medium">Current value:</p>
<p className="text-sm text-muted-foreground">{inputValue}</p>
</div>
<div className="space-y-2">
<p className="text-sm font-medium">Debounced value:</p>
<p className="text-sm text-muted-foreground">{debouncedValue}</p>
</div>
<div className="space-y-2">
<p className="text-sm font-medium">API Response:</p>
<p className="text-sm text-muted-foreground">{apiResult}</p>
</div>
</div>
);
}
// Search Demo
export function DebounceSearchDemo() {
const [search, setSearch] = useState('');
const debouncedSearch = useDebounce(search, 500);
const [results, setResults] = useState<string[]>([]);
const [isSearching, setIsSearching] = useState(false);
// Имитация поиска
useEffect(() => {
if (debouncedSearch) {
setIsSearching(true);
// Имитация API запроса
setTimeout(() => {
setResults([
`Result 1 for "${debouncedSearch}"`,
`Result 2 for "${debouncedSearch}"`,
`Result 3 for "${debouncedSearch}"`,
]);
setIsSearching(false);
}, 1000);
} else {
setResults([]);
}
}, [debouncedSearch]);
return (
<div className="flex flex-col gap-4 w-[300px]">
<div className="space-y-2">
<p className="text-sm text-muted-foreground">
Search with debounce
</p>
<Input
type="search"
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder="Search..."
/>
</div>
<div className="space-y-2">
{isSearching ? (
<p className="text-sm">Searching...</p>
) : (
results.map((result, index) => (
<p key={index} className="text-sm">
{result}
</p>
))
)}
</div>
</div>
);
}
// Counter Demo
export function DebounceCounterDemo() {
const [count, setCount] = useState(0);
const debouncedCount = useDebounce(count, 1000);
const [savedCounts, setSavedCounts] = useState<number[]>([]);
useEffect(() => {
// Сохраняем значение только когда debouncedCount изменился
if (debouncedCount > 0) {
setSavedCounts(prev => [...prev, debouncedCount]);
}
}, [debouncedCount]);
return (
<div className="flex flex-col gap-4 w-[300px]">
<div className="space-y-2">
<p className="text-sm text-muted-foreground">
Click rapidly to see debounce effect
</p>
<Button
onClick={() => setCount(c => c + 1)}
className="w-full"
>
Increment: {count}
</Button>
</div>
<div className="space-y-2">
<p className="text-sm font-medium">Debounced count:</p>
<p className="text-sm text-muted-foreground">{debouncedCount}</p>
</div>
<div className="space-y-2">
<p className="text-sm font-medium">Saved counts:</p>
<div className="flex flex-wrap gap-2">
{savedCounts.map((savedCount, index) => (
<span
key={index}
className="text-sm bg-muted px-2 py-1 rounded"
>
{savedCount}
</span>
))}
</div>
</div>
</div>
);
}






