PromptBase
Upgrade
Close icon
General
Home
Marketplace
Create
Hire
Login
Chat
Sell
Explore

Skill Details

Runtime
Any model
Example user message
[userMessage]: My React search box intermittently shows results for an older query. Code: `async function search(q){ const r=await fetch('/api/search?q='+q); const data=await r.json(); setResults(data); }` `useEffect(()=>{ if(query) search(query); },[query]);` Observed timing: user types `re`, then quickly `react`. The `react` request returns after 120 ms. The earlier `re` request returns after 640 ms. The final UI sometimes shows `re` results. There is no AbortController, request ID, or sequence check. Use only this evidence. Prove the exact interleaving, choose the smallest correctness fix, explain why debounce is not required, and give me a deterministic regression test without claiming you ran it.
Example agent response
## EVIDENCE STATE Mode: EVIDENCE. The supplied code, reported request timings, and final UI observation are sufficient to construct the failing ordering. I did not run the component or inspect the API. ## EVENT TIMELINE **A — search for `re`** - Trigger: `query` becomes `re`. - Captured input: `q = "re"`. - Async boundary: `fetch('/api/search?q=re')`. - Observed completion: about 640 ms. - Commit: `setResults(dataFromRe)`. **B — search for `react`** - Trigger: `query` later becomes `react`. - Captured input: `q = "react"`. - Async boundary: `fetch('/api/search?q=react')`. - Observed completion: about 120 ms. - Commit: `setResults(dataFromReact)`. Both operations write the same React state target: `results`. ## HAPPENS-BEFORE GRAPH Guaranteed: - A starts before B because the user typed `re` before `react`. - Inside each call, its own fetch resolves before its own `setResults`. Not guaranteed: - A completes before B. - A commits before B. Observed completion order is the reverse of start order: A starts → B starts → B completes/commits → A completes/commits. The code has no check tying a completion to the latest query. ## RACE WITNESS **Verdict: PROVED RACE** 1. Query becomes `re`; A starts. 2. Query becomes `react`; B starts. 3. B resolves first at about 120 ms. 4. B commits `react` results. 5. A resolves later at about 640 ms. 6. A commits stale `re` results. 7. Final `results` reflects an older intent although `query` is `react`. Missing correctness rule: **only the completion belonging to the latest search intent may commit results.** ## GUARD ROUTE Best fit: **monotonic generation/request token**. Older requests may finish, but only the newest request should be authoritative. Correctness depends on commit admission, not on reducing request frequency. An AbortController can cancel superseded fetches, but cancellation is optional optimization here. A sequence check still enforces the state invariant if an older request resolves. Why debounce is not required: Debounce suppresses or delays intermediate searches. The supplied requirement is not “wait until typing stops”; it is “do not let an old completion overwrite a newer intent.” A commit guard solves that exact problem without changing search cadence. ## STABILIZATION PATCH Minimal pattern: - Keep a monotonically increasing search generation. - Increment it whenever a search starts. - Capture that generation in the request. - Before `setResults`, compare it with the current generation. - Commit only when they match. Conceptually: `const id = ++latestSearchId.current` → await fetch → await parse → `if (id !== latestSearchId.current) return` → `setResults(data)` **Preserved behavior** - Every current query may still start a search. - Fast responses still render immediately. - No new library or state architecture is required. **Intentionally changed** - A superseded completion may no longer mutate `results`. **Remaining surface** - Superseded network work still occurs. Add cancellation only if removing wasted work matters. **Rollback** - Revert only the generation guard; no API contract change is required. ## DETERMINISTIC REPRO Use two manually controlled promises instead of real network delay. 1. Render with query `re`; capture resolver A. 2. Update query to `react`; capture resolver B. 3. Resolve B first with `react` results. 4. Assert `react` results are shown. 5. Resolve A second with `re` results. 6. On old code, assert the UI incorrectly becomes `re`. 7. Apply the generation guard. 8. Repeat the identical resolver order. 9. Assert the UI remains `react`. Pass condition: the same reversed completion order can no longer make an older query authoritative. No sleep duration is needed; the test controls completion order directly. ## RECOVERY DELTA No additional evidence is required to establish this specific race. More evidence is needed only to decide whether cancellation is worth adding, such as request volume, API cost, or existing fetch-wrapper behavior.
🟧 Claude Skill

Async UI Race Condition Lab

Add to Cart
PromptBase Select
Or get it with Select10 Select prompts/mo — under $2 each
Learn more
Instant accessInstant access
Usage rightsCommercial use
Money-back guaranteeMoney‑back
By purchasing this skill, you agree to our terms of service
Tested icon
Guide icon
Free credits icon
Turn intermittent frontend bugs into a provable event interleaving before changing code. ASYNC UI RACE CONDITION LAB ⏱ Event Timeline Extractor 🔗 Happens-Before Graph 🧪 Race Witness Generator 🛡 Stale-Write Guard Router 🩹 Minimal Stabilization Ladder 🎯 Deterministic Repro Harness Paste frontend async code plus symptom/timing evidence. Get the competing operations, failing schedule, narrowest safe fix, and deterministic regression test—not “add debounce and hope.”
...more
Added 18 hours ago
Report
Browse Marketplace