import { useState, useEffect, useRef } from "react"; // Mock API fetch async function fetchSystemLogs(options) { await new Promise(r => setTimeout(r, 100)); return [ { id: 1, type: "info", message: "Database connection established." }, { id: 2, type: "warning", message: "CPU utilization exceeded 85%." }, { id: 3, type: "info", message: "SSL certificate renewed successfully." } ]; } export default function App() { const [logs, setLogs] = useState([]); const [requestCount, setRequestCount] = useState(0); const [errorBanner, setErrorBanner] = useState(""); const countRef = useRef(0); useEffect(() => { const b = document.body; b.style.background = "#fafafa"; b.style.margin = "0"; return () => { b.style.background = ""; b.style.margin = ""; }; }, []); // BUG: Passing an inline object literal directly as a dependency in useEffect. // Because {} !== {} in JavaScript, the 'options' object is a new reference // on every single render. This triggers the effect, which fetches data and // updates state, causing another render, which creates a new 'options' object, // triggering the effect again, leading to an infinite fetch loop! const options = { fetchPolicy: "network-only" }; useEffect(() => { // Safeguard to prevent crashing the Sandpack browser tab if (countRef.current > 40) { setErrorBanner("⚠️ CRITICAL: Infinite request loop detected! Over 40 API requests triggered."); return; } countRef.current += 1; setRequestCount(countRef.current); fetchSystemLogs(options).then((data) => { setLogs(data); }); }, [options]); // Bug lives here return ( <div style={styles.page}> <div style={styles.card}> <div style={styles.header}> <h1 style={styles.h1}>Activity Monitor</h1> <div data-testid="request-badge" style={requestCount > 10 ? styles.badgeAlert : styles.badge}> Requests: {requestCount} </div> </div> {errorBanner && ( <div data-testid="error-banner" style={styles.errorBanner}> {errorBanner} </div> )} <p style={styles.sub}> Real-time feed of system events and alerts. </p> <div style={styles.logsList}> {logs.map((log) => ( <div key={log.id} style={styles.logRow}> <span style={log.type === "warning" ? styles.typeWarning : styles.typeInfo}> [{log.type.toUpperCase()}] </span> <span style={styles.logMessage}>{log.message}</span> </div> ))} </div> </div> </div> ); } const styles = { page: { display: "flex", justifyContent: "center", padding: "40px 20px", fontFamily: "system-ui, sans-serif" }, card: { background: "#fff", borderRadius: 12, padding: "24px", width: "100%", maxWidth: 460, boxShadow: "0 4px 6px -1px rgba(0,0,0,0.1)" }, header: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 6 }, h1: { margin: 0, fontSize: 20, fontWeight: 600, color: "#111827" }, sub: { margin: "0 0 20px", fontSize: 14, color: "#6B7280" }, badge: { background: "#F3F4F6", color: "#374151", fontSize: 12, fontWeight: 600, padding: "4px 10px", borderRadius: 9999 }, badgeAlert: { background: "#FEE2E2", color: "#EF4444", fontSize: 12, fontWeight: 600, padding: "4px 10px", borderRadius: 9999 }, errorBanner: { background: "#FEF2F2", border: "1px solid #FCA5A5", borderRadius: 8, padding: "12px", color: "#B91C1C", fontSize: 13, fontWeight: 500, marginBottom: 16 }, logsList: { border: "1px solid #E5E7EB", borderRadius: 8, overflow: "hidden", background: "#FAFBFB" }, logRow: { display: "flex", gap: 8, padding: "12px 16px", borderBottom: "1px solid #E5E7EB", fontSize: 13, color: "#374151" }, typeInfo: { color: "#3B82F6", fontWeight: 600 }, typeWarning: { color: "#F59E0B", fontWeight: 600 }, logMessage: { color: "#1F2937" } };
Click "Run checks" to verify your solution.