Connect Search with a Debounced Query
Connect Search with a Debounced Query
Make the search box responsive while preventing a request on every keystroke. The local input value should change immediately; the URL should change only after the user pauses briefly.
Step 1 — Track the input value locally
Add local state initialized from the server-supplied query prop.
const [searchValue, setSearchValue] = useState(query);
Keep it synchronized when browser navigation or another control changes the query.
useEffect(() => {
setSearchValue(query);
}, [query]);
Step 2 — Hold the debounce timer
Add a ref to remember the active timeout.
const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
Step 3 — Create the search handler
When the user types, update the local state immediately. Clear any previous timer, then schedule pushParams for 400 milliseconds later.
function onSearchChange(value: string) {
setSearchValue(value);
if (debounceRef.current) clearTimeout(debounceRef.current);
debounceRef.current = setTimeout(() => pushParams({ q: value }), 400);
}
Step 4 — Connect the input
Replace the read-only behavior with the local value and the handler.
value={searchValue}
onChange={(e) => onSearchChange(e.target.value)}
Checkpoint
Type a title quickly. The input should respond to every keystroke, but the URL and movie results should update after the short pause rather than on every key press.