import { useState, useEffect } from "react"; // Mock API that takes longer for shorter strings to simulate a race condition async function checkUsername(username) { const isTaken = username === "amm" || username === "admin"; // The delay for "amm" is 600ms, but for "ammar" is only 200ms const delay = username.length <= 3 ? 600 : 200; await new Promise(r => setTimeout(r, delay)); return { available: !isTaken }; } export default function App() { const [username, setUsername] = useState(""); const [status, setStatus] = useState(""); // "checking", "available", "taken" useEffect(() => { const b = document.body; b.style.background = "#fafafa"; b.style.margin = "0"; return () => { b.style.background = ""; b.style.margin = ""; }; }, []); useEffect(() => { if (!username) { setStatus(""); return; } setStatus("checking"); // BUG: Missing cancellation/active tracking. // If "amm" (takes 600ms) is typed, then "ammar" (takes 200ms) is typed right after, // "ammar" resolves first (available), then "amm" resolves (taken) and overwrites the state. checkUsername(username).then((res) => { setStatus(res.available ? "available" : "taken"); }); }, [username]); return ( <div style={styles.page}> <div style={styles.card}> <h1 style={styles.h1}>Sign Up</h1> <p style={styles.sub}>Choose a unique username to continue.</p> <input data-testid="username-input" value={username} onChange={(e) => setUsername(e.target.value)} placeholder="Username" style={styles.input} /> <div style={styles.statusBox}> {status === "checking" && <span data-testid="status-checking" style={styles.checking}>Checking availability...</span>} {status === "available" && <span data-testid="status-available" style={styles.available}>✓ Username is available</span>} {status === "taken" && <span data-testid="status-taken" style={styles.taken}>✗ Username is already taken</span>} </div> </div> </div> ); } const styles = { page: { display: "flex", justifyContent: "center", padding: "48px 20px", fontFamily: "system-ui, sans-serif" }, card: { background: "#fff", borderRadius: 12, padding: "32px", width: "100%", maxWidth: 360, boxShadow: "0 4px 6px -1px rgba(0,0,0,0.1)" }, h1: { margin: "0 0 8px", fontSize: 24, fontWeight: 600, color: "#111827" }, sub: { margin: "0 0 24px", fontSize: 14, color: "#6B7280" }, input: { width: "100%", boxSizing: "border-box", padding: "12px 16px", fontSize: 16, borderRadius: 8, border: "1px solid #D1D5DB", outline: "none", transition: "border-color 0.2s" }, statusBox: { marginTop: 12, minHeight: 20, fontSize: 14, fontWeight: 500 }, checking: { color: "#6B7280" }, available: { color: "#10B981" }, taken: { color: "#EF4444" } };
Click "Run checks" to verify your solution.