import Link from "next/link"; import { notFound } from "next/navigation"; import BotaoCopiarIsbn from "@/app/components/BotaoCopiarIsbn"; import type { Metadata } from "next"; // Experimento da Parte 7 (opcional): substitui app/livros/[id]/page.tsx numa // CÓPIA do projeto aula-13-dados-api. Troque o módulo abaixo entre // "@/lib/livros", "@/lib/livros-axios" e "@/lib/livros-axios-cache" e conte // quantos GET /livros/:id chegam à API a cada visita. import { buscarLivro } from "@/lib/livros"; // O título da aba usa o mesmo livro que a página: duas chamadas iguais na // mesma renderização. export async function generateMetadata({ params }: PageProps<"/livros/[id]">): Promise { const { id } = await params; const livro = /^[1-9]\d*$/.test(id) ? await buscarLivro(Number(id)) : undefined; return { title: livro?.titulo ?? "Livro" }; } export default async function Page({ params }: PageProps<"/livros/[id]">) { // `params` é uma Promise desde o Next.js 16 — daí o `await` e o `async` na // função. E `id` chega como texto, mesmo quando a URL parece um número. const { id } = await params; // `/livros/abc` não é um livro que falta: é um endereço que não pode // existir. Respondemos 404 aqui, sem gastar uma chamada — a API // responderia 400, e a página trataria isso como falha. // Aceita somente a representação decimal de um inteiro positivo. if (!/^[1-9]\d*$/.test(id) || !Number.isSafeInteger(Number(id))) { notFound(); } // Quem chega aqui já passou pelo `loading.tsx` do segmento: enquanto este // `await` não termina, o navegador está mostrando o esqueleto. const livro = await buscarLivro(Number(id)); // `notFound()` interrompe a renderização e entrega o `not-found.tsx` mais // próximo, com status 404. Não é preciso devolver nada depois disso. if (!livro) { notFound(); } return (

Acervo

{livro.titulo}

Autor
{livro.autor.nome}
Ano
{livro.ano}
ISBN
{livro.isbn}
Editora
{/* A editora é opcional no modelo: o componente precisa tratar o nulo. */}
{livro.editora ? livro.editora.nome : "não informada"}
); }