Components
Delay function execution with useDebounceCallback, providing options for canceling, flushing, and checking if a call is pending.
npx shadcn@latest add https://21st.dev/r/strlrd-29/use-debounce-callbackLoading preview...
'use client'
import { useDebounceCallback } from "@/components/hooks/use-debounce-callback"
import { Button } from "@/components/ui/button"
import { Card } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { Slider } from "@/components/ui/slider"
import { useState, useCallback } from "react"
import { toast } from "sonner"
import { Clock, Loader2 } from "lucide-react"
export function UseDebounceCallbackDemo() {
const [value, setValue] = useState("")
const [delay, setDelay] = useState(500)
const [isPending, setIsPending] = useState(false)
const mockApiCall = async (searchTerm: string) => {
setIsPending(true)
try {
await new Promise(resolve => setTimeout(resolve, 500))
toast.success(`API called with: "${searchTerm}"`)
} finally {
setIsPending(false)
}
}
const debouncedSearch = useDebounceCallback(
useCallback(async (searchTerm: string) => {
setValue(searchTerm)
await mockApiCall(searchTerm)
}, []),
delay
)
return (
<div className="grid grid-cols-2 gap-6 max-w-4xl mx-auto">
{/* Left Column - Interactive Demo */}
<Card className="p-6">
<div className="space-y-6">
<div className="space-y-2">
<h3 className="text-lg font-medium">Live Demo</h3>
<p className="text-sm text-muted-foreground">
Type to see debounced API calls in action
</p>
</div>
<div className="space-y-4">
<div className="relative">
<Input
type="text"
placeholder="Start typing..."
onChange={(e) => debouncedSearch(e.target.value)}
className="pr-8"
/>
{isPending && (
<Loader2 className="w-4 h-4 absolute right-3 top-3 animate-spin text-muted-foreground" />
)}
</div>
<div className="space-y-2">
<div className="flex items-center gap-2 text-sm">
<Clock className="w-4 h-4" />
<span>Debounce delay:</span>
<span className="font-mono">{delay}ms</span>
</div>
<Slider
value={[delay]}
onValueChange={([newDelay]) => setDelay(newDelay)}
min={100}
max={2000}
step={100}
/>
</div>
</div>
<div className="p-3 rounded-lg bg-muted">
<div className="text-sm font-medium mb-1">Current Value:</div>
<code className="text-xs">
{value || 'Empty'}
</code>
</div>
<div className="flex gap-2">
<Button
variant="outline"
size="sm"
onClick={() => debouncedSearch.cancel()}
>
Cancel Pending
</Button>
<Button
variant="outline"
size="sm"
onClick={() => debouncedSearch.flush()}
>
Flush Pending
</Button>
</div>
</div>
</Card>
{/* Right Column - Documentation */}
<Card className="p-6">
<div className="space-y-6">
<div>
<h3 className="text-lg font-medium mb-2">Hook Usage</h3>
<pre className="bg-muted p-3 rounded-md text-xs">
{`const debouncedFn = useDebounceCallback(
(value) => {
// Your callback logic
},
500, // delay in ms
{
leading: false,
trailing: true,
}
)
// Control methods
debouncedFn.cancel() // Cancel pending
debouncedFn.flush() // Execute immediately
debouncedFn.isPending() // Check status`}
</pre>
</div>
<div className="space-y-4">
<div>
<h4 className="text-sm font-medium mb-2">Features</h4>
<ul className="list-disc list-inside space-y-1 text-sm text-muted-foreground">
<li>Debounces function calls</li>
<li>Configurable delay</li>
<li>Cancel pending executions</li>
<li>Force immediate execution</li>
<li>Check pending status</li>
</ul>
</div>
<div>
<h4 className="text-sm font-medium mb-2">Common Use Cases</h4>
<ul className="list-disc list-inside space-y-1 text-sm text-muted-foreground">
<li>Search input handling</li>
<li>Form validation</li>
<li>API request throttling</li>
<li>Window resize handlers</li>
</ul>
</div>
</div>
</div>
</Card>
</div>
)
}