State as a snapshot

See that a handler still reads the watched flag from the click, even after you set it.

The setter does not change this render

setWatched(true) asks for the next render. The watched in this call is still false. It is a const for this run.

import "./styles.css";
import ShowCard from "./ShowCard";

export default function App() {
  return (
    <div className="page">
      <ShowCard
        title="The Bear"
        year={2022}
        genre="Drama"
        rating={8.6}
        still="still-warm"
      />
    </div>
  );
}

Press Watched. The pill appears on the next render. The console printed watched is still false on this one.

The handler sees the click-time snapshot

The same snapshot feeds an alert. This click still sees false, so the alert says the show was just marked.

import "./styles.css";
import ShowCard from "./ShowCard";

export default function App() {
  return (
    <div className="page">
      <ShowCard
        title="The Bear"
        year={2022}
        genre="Drama"
        rating={8.6}
        still="still-warm"
      />
    </div>
  );
}

Press Watched. The alert reads Just marked, then the pill appears. Press it again: the alert reads Already watched. The badge is the new render. The alert is the old snapshot.

Common mistakes

  • Reading state on the next line. setWatched(true) does not change watched in this call.
  • Writing the new value into the log by hand. Log watched itself if you want to see the snapshot.
  • Waiting for React before you read. The next render has the new value. This render does not.

Exercise

The log is right — it prints the snapshot — but the pill never appears. The still reads a let that the handler assigns, instead of watched.

Fix the badge. After one click the still shows Watched, and the console reads:

watched is still false

Hint: put the pill on watched. Leave the log as it is, so you can see the snapshot.

import "./styles.css";
import ShowCard from "./ShowCard";

export default function App() {
  return (
    <div className="page">
      <ShowCard
        title="The Bear"
        year={2022}
        genre="Drama"
        rating={8.6}
        still="still-warm"
      />
    </div>
  );
}