Build a search box that fetches results as the user types — but does it cheaply. Every keystroke could fire a network request; a good realtime search avoids that three ways. It debounces typing so it only searches once you pause, caches each query's results so repeating a search is instant, and dedupes in-flight requests so two identical searches that overlap share a single fetch instead of hitting the network twice. This is the React variant, built with useState for what renders and useRef for the caches.
The starter App.tsx renders the resting UI — an empty input, a "Type to search" status, and no results. Wire up the logic:
useEffect keyed on query, wait 300ms after the last keystroke before searching (setTimeout, cleared on the next change).useRef Map of query to results. If the query is already cached, show it instantly and set the status to cached.useRef Map of query to the pending Promise. If a fetch for that exact query is already running, await the same promise instead of starting a second one. When it resolves, store the result in the cache and remove the in-flight entry.A provided searchAPI(query) resolves after ~400ms with the items whose name contains the query (case-insensitive).
re, pause. After 300ms it fetches; the status reads fetched · N results and the list fills in.re again. This time it is in the cache, so results appear instantly and the status reads cached · N results.re, and before the 400ms fetch finishes, trigger re again. Only one request goes out — the second search awaits the first's promise.useRef, not useState.Re and re hit the same cache entry.searchAPI never rejects — realistic LRU and error states are out of scope here.Unlock the solution & editor
Runnable editor + tests
Solve in the browser with instant Jest feedback.
Detailed solutions
Walkthroughs, edge cases, and complexity notes.
Multi-framework variants
React, Vue, Vanilla, Angular — same question, different stacks.