← Back to Docs
Recipe

Smart typeahead

Debounced search input with keyboard navigation, loading states, and result highlighting.

Ingredients

  • Controlled input with debounce hook
  • AbortController for in-flight requests
  • Arrow-key + Enter navigation
  • Highlight matched substring in results
  • Empty, loading, and error states

Steps

  1. Create a useDebounce hook wrapping setTimeout.
  2. Wire the input value through debounce, firing a fetch when the debounced value changes.
  3. Store an AbortController ref and call .abort() before each new request.
  4. Track activeIndex for keyboard navigation; clamp with Math.min/max.
  5. Split result text on the query substring and wrap matches in a highlighted <mark> element.
  6. Render a spinner while loading, a message when empty, and an inline error banner on failure.

Tip: Keep the debounce window between 200–350 ms. Shorter feels jittery; longer feels sluggish on fast typists.