Stop 10 · API IntegrationTopics · 7/16

Search

Part of the Frontend Developer Roadmap

In short

A search box that fires a request on every single keystroke will hammer your server and show flickering results. A few small tricks make search feel quick and calm.

Letting users query a data set by keyword — usually debounced client input triggering a server-side search endpoint.

The jaadu orders at a chai stall while the chai seller waits patiently with the kettle.

Think of it like this

The chai wala who waits

A good chai wala doesn't start pouring the moment you say 'ek'. He waits till you finish: 'ek cutting, kam cheeni'. Debouncing is that pause. Your app waits until the user stops typing, then searches once.

Watch it happen

Typing "react" with a 300 ms debounce

Search box
Timer
API

q = "r"

1/5The first letter starts a 300 ms timer. No request yet.

The big ideas

What you need to know

Debounce the input

Wait around 300 ms after the last keystroke before calling the API. Typing 'react' becomes one request, not five.

Ignore stale answers

Older requests can return after newer ones. Cancel them or ignore their results.

Encode the query

Use encodeURIComponent or URLSearchParams, so spaces, & and # don't break the URL.

Handle empty and no results

Show nothing for an empty box, and a friendly 'No results for ...' when nothing matches.

See it in code

Walk through the code

tsx
1const [q, setQ] = useState("");2const [results, setResults] = useState<User[]>([]);3 4useEffect(() => {5  if (!q.trim()) return setResults([]);6  const controller = new AbortController();7  const timer = setTimeout(() => {8    fetch(`/api/users?q=${encodeURIComponent(q)}`, { signal: controller.signal })9      .then((r) => r.json())10      .then(setResults)11      .catch(() => {});12  }, 300);13  return () => { clearTimeout(timer); controller.abort(); };14}, [q]);

1/4Empty box? Clear the results and skip the request.

Each keystroke clears the old timer and aborts the old request. Only the last one, 300 ms after typing stops, actually reaches the screen.

Save yourself the pain

Common mistakes

Oops

Calling the search API inside onChange on every keystroke.

Do this instead

Debounce it, so the request only goes out after the user pauses.

Oops

Showing whichever response arrives last, even if it's for an old query.

Do this instead

Abort the previous request in the effect cleanup, so old answers never overwrite new ones.

Your mission

Build a debounced search

~30 min

Quick check

A user types 'laptop' quickly with a 300 ms debounce. Roughly how many search requests go out?

Go deeper

  1. 1Build a debounced search box wired to a real search endpoint.
  2. 2Show a loading state while a search request is in flight.
  3. 3Handle and display the empty 'no results' state clearly.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge