Debuggler LogoDebuggler
All challenges
The Amnesia Auto-SaveDashboardNotion & Slate Editors
import { useState, useEffect } from "react";

export default function App() {
  const [text, setText] = useState("");
  const [saveStatus, setSaveStatus] = useState("idle"); // idle, saving, saved

  useEffect(() => {
    const b = document.body;
    b.style.background = "#fafafa"; b.style.margin = "0";
    return () => { b.style.background = ""; b.style.margin = ""; };
  }, []);

  useEffect(() => {
    // Background auto-save every 4 seconds
    const interval = setInterval(() => {
      setSaveStatus("saving");
      
      // Simulate API save
      setTimeout(() => {
        // BUG: Stale closure. text is permanently "" because the dependency array is [].
        // It saves the empty string, and then updates the UI state with that empty string,
        // erasing whatever the user typed in the meantime.
        setText(text); // In a real app this might be setting the last confirmed saved state
        setSaveStatus("saved");
        
        setTimeout(() => setSaveStatus("idle"), 1000);
      }, 500);
    }, 4000);

    return () => clearInterval(interval);
  }, []); // Empty dependency array causes the bug

  return (
    <div style={styles.page}>
      <div style={styles.card}>
        <div style={styles.header}>
          <h1 style={styles.h1}>Quick Notes</h1>
          <span data-testid="save-status" style={styles.status}>
            {saveStatus === "saving" ? "Saving..." : saveStatus === "saved" ? "Saved!" : ""}
          </span>
        </div>
        <textarea
          data-testid="note-input"
          value={text}
          onChange={(e) => setText(e.target.value)}
          placeholder="Start typing your notes here..."
          style={styles.textarea}
        />
      </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: 500, boxShadow: "0 4px 6px -1px rgba(0,0,0,0.1)" },
  header: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 },
  h1: { margin: 0, fontSize: 18, fontWeight: 600, color: "#111827" },
  status: { fontSize: 13, color: "#6B7280", fontStyle: "italic", minWidth: 60, textAlign: "right" },
  textarea: { width: "100%", boxSizing: "border-box", height: 200, padding: "16px", borderRadius: 8, border: "1px solid #D1D5DB", outline: "none", resize: "none", fontSize: 15, fontFamily: "inherit", lineHeight: 1.5 }
};

Type some text in the notepad. Every 4 seconds, the auto-save runs and erases your work because it saves the initial empty state. Fix the stale closure.

After you fix it

  • The auto-save interval should capture the latest typed text, not the initial empty string.
  • The text area should not clear out after an auto-save.

Click "Run checks" to verify your solution.