A small hook that stops a delayed callback from firing with yesterday's state — and keeps the timer's identity stable even when the callback changes on every render.
The Problem
Here is a search box that looks right at a glance. Every keystroke updates the input and schedules a request. The previous timer is cleared, so only the last keystroke should fetch.
function SearchBox () { const [ query , setQuery ] = useState ( "" ); const [ results , setResults ] = useState < string [] > ([]);
const scheduleSearch = useMemo (() => { let timer = 0 ; return () => { window . clearTimeout ( timer ); timer = window . setTimeout (() => { fetch ( `/api/search?q= ${ query } ` ) . then (( response ) => response . json ()) . then ( setResults ); }, 300 ); }; }, []);
return ( < input onChange = { ( event ) => { setQuery ( event . target . value ); scheduleSearch (); } } /> ); }
Enter fullscreen mode
Exit fullscreen mode
The input is live.…