Searching TVMaze
The answer to the exercise in Searching TVMaze.
Each hit is { score, show }. fromTvmaze(item) reads item.genres and
throws, so the catch sets "error". Pass item.show so the mapper
gets a real show.
import { useState } from "react"; import "./styles.css"; import { fromTvmaze } from "./show"; import SearchForm from "./SearchForm"; 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); const [query, setQuery] = useState(""); const [results, setResults] = useState([]); const [status, setStatus] = useState("idle"); function handleToggle(id) { setShows( shows.map((show) => show.id === id ? { ...show, watched: !show.watched } : show ) ); } async function handleSearch(event) { event.preventDefault(); const trimmed = query.trim(); if (!trimmed) { setResults([]); setStatus("empty"); return; } setStatus("loading"); setResults([]); try { const response = await fetch( "https://api.tvmaze.com/search/shows?q=" + encodeURIComponent(trimmed) ); if (!response.ok) { throw new Error("Request failed"); } const data = await response.json(); setResults(data.map((item) => fromTvmaze(item.show))); // each hit wraps the show setStatus("success"); } catch { setStatus("error"); } } const watched = shows.filter((show) => show.watched).length; return ( <div className="page"> <header className="header"> <h1>My watchlist</h1> <p className="count"> {shows.length} shows · {watched} watched </p> </header> <SearchForm query={query} onQueryChange={setQuery} onSearch={handleSearch} disabled={status === "loading"} /> {status === "loading" ? ( <p className="status">Searching…</p> ) : null} {status === "empty" ? ( <p className="status">Type a show name first.</p> ) : null} {status === "error" ? ( <p className="status status-error"> Could not load shows. Try again. </p> ) : null} {status === "success" && results.length === 0 ? ( <p className="status">No shows for that name.</p> ) : null} {status === "success" && results.length > 0 ? ( <div className="results"> <p className="section-title">Results</p> <ShowList shows={results} /> </div> ) : null} <ShowList shows={shows} onToggle={handleToggle} /> </div> ); }
Resize editor and preview
Resize sandbox height