Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Tela de Detalhe

O EventDetail precisa buscar os dados de um único evento. O backend ainda não tem um endpoint GET /api/events/:id — ele retorna a lista completa. Então vamos buscar a lista e filtrar pelo id no frontend1.

Crie src/EventDetail.tsx:

Arquivo: web/src/EventDetail.tsx
import { useState, useEffect } from "react";
import { useParams, Link } from "react-router-dom";
import { Event } from "./types";

function EventDetail() {
  const { id } = useParams<{ id: string }>();
  const [event, setEvent] = useState<Event | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    fetch("/api/events")
      .then((res) => {
        if (!res.ok) throw new Error(`Erro ${res.status}`);
        return res.json();
      })
      .then((data: Event[]) => {
        const found = data.find((ev) => ev.id === Number(id));
        if (!found) throw new Error("Evento não encontrado");
        setEvent(found);
      })
      .catch((err) => setError(err.message))
      .finally(() => setLoading(false));
  }, [id]);

  if (loading) return <p>Carregando...</p>;
  if (error) return <p>{error}</p>;
  if (!event) return null;

  return (
    <div>
      <Link to="/">← Voltar</Link>
      <h1>{event.title}</h1>
      <time dateTime={event.date}>
        {new Date(event.date).toLocaleString("pt-BR", {
          dateStyle: "full",
          timeStyle: "short",
        })}
      </time>
      <p>{event.description}</p>
      <p>📍 {event.location}</p>
      <p>Capacidade: {event.capacity} pessoas</p>
      <p>Organizado por {event.organizer_name}</p>
    </div>
  );
}

export default EventDetail;

Código 7-9: Tela de detalhe que exibe um único evento.

O useParams extrai o id da URL. O useEffect tem [id] na lista de dependências — se o usuário navegar de /events/3 para /events/7 sem voltar à lista, o efeito roda novamente com o novo id.

A data aqui usa dateStyle: "full" para mostrar o formato extenso: “segunda- feira, 15 de setembro de 2026, 08:00”. A lista usava o formato curto. Cada tela mostra o nível de detalhe adequado.


  1. Buscar a lista inteira para exibir um evento é desperdício de banda e processamento. O exercício 6 do capítulo Armazenando e Servindo Dados propõe criar o endpoint GET /api/events/:id. Se você o implementou, use-o aqui em vez de buscar a lista completa. ↩