AniUI Academy
medium+180 XP

Build a debounced search input

Wire a search input so that typing doesn't search on every keystroke — it should wait for a 300ms pause in typing before running the search.

Every keystroke inside that pause resets the wait — only the final value, after things go quiet, actually counts as a search.

Requirements

  • There is exactly one `<input id="search-input">`.
  • An element `data-testid="search-count"` shows how many searches have actually run, starting at 0.
  • An element `data-testid="last-query"` shows the text of the most recent completed search.
  • A search only runs 300ms after the last keystroke — typing continuously must not increase the count until it stops.

Your workspace

import { useState } from "react";

export default function App() {
  const [count, setCount] = useState(0);
  const [lastQuery, setLastQuery] = useState("");

  function handleChange(e) {
    // TODO: only "search" (update lastQuery and increment count) 300ms
    // after the user stops typing — not on every keystroke.
    setLastQuery(e.target.value);
    setCount((c) => c + 1);
  }

  return (
    <div style={{ fontFamily: "sans-serif", padding: 16 }}>
      <input
        id="search-input"
        onChange={handleChange}
        placeholder="Search..."
        style={{ padding: 8, width: "100%", boxSizing: "border-box" }}
      />
      <p>Searches performed: <span data-testid="search-count">{count}</span></p>
      <p>Last query: <span data-testid="last-query">{lastQuery}</span></p>
    </div>
  );
}

Ready to check it?

5 tests run against your rendered component, right here in your browser. Sign in to claim the XP when you pass.

Stuck? The react course covers the ideas this problem is built on.