← Back to the exercise

The watchlist layout

The answer to the exercise in The watchlist layout.

watched was frozen in useState on the first render. Tick a box and that number never runs again. Read shows.filter during render instead, so the header always matches the cards.

import { useState } from "react";
import "./styles.css";
import ShowList from "./ShowList";

const start = [
  { id: "s1", title: "The Bear", year: 2022, genre: "Drama", genres: ["Drama"], rating: 8.6, still: "still-warm", watched: false },
  { id: "s2", title: "Severance", year: 2022, genre: "Thriller", genres: ["Thriller"], rating: 8.7, still: "still-cold", watched: false },
  { id: "s3", title: "Andor", year: 2022, genre: "Sci-Fi", genres: ["Sci-Fi"], rating: 8.4, still: "still-dusty", watched: true },
];

export default function App() {
  const [shows, setShows] = useState(start);

  function handleToggle(id) {
    setShows(
      shows.map((show) =>
        show.id === id ? { ...show, watched: !show.watched } : show
      )
    );
  }

  const watched = shows.filter((show) => show.watched).length; // from this render, not a stored count

  return (
    <div className="page">
      <header className="header">
        <h1>My watchlist</h1>
        <p className="count">
          {shows.length} shows · {watched} watched
        </p>
      </header>
      <ShowList shows={shows} onToggle={handleToggle} />
    </div>
  );
}