01Inline useEffect + setTimeout
Debounce logic lives directly inside the component that owns the input.
export function TaskSearch() { const [draft, setDraft] = useState(''); const [query, setQuery] = useState(''); useEffect(() => { const id = setTimeout(() => setQuery(draft), 300); return () => clearTimeout(id); }, [draft]); const { data } = useTasks({ search: query }); return ( <input value={draft} onChange={(e) => setDraft(e.target.value)} placeholder="Filter tasks…" /> ); }
Pro
Con
Zero new abstractions to learn
Logic duplicated everywhere search exists
Easy to step through in devtools
Two pieces of state for one conceptual value
No dependency or bundle change
Delay constant is buried in component body
Bundle impact: +0 kb
Testability: medium
Reuse: low
SSR safe: yes