Capítulo 304 de 456
Pages Router lida com mutação de dados via API Routes: form no client faz fetch(POST) pra um endpoint em pages/api/*, que roda no servidor e pode usar env vars sensíveis com segurança.
pages/api/submit.ts recebe req.body e devolve JSON; roda no servidor, então segredos (API keys) nunca vazam pro client.required, type="email") cobre o básico; validação de schema (Zod, Valibot) no servidor cobre o caso robusto, antes de mutar dado.useState local pra isLoading/error, desabilitando o botão e mostrando mensagem durante o fetch.res.redirect(307, ...) na API Route pra levar o usuário à página resultante (ex.: /post/${id}).async function onSubmit(event: SubmitEvent<HTMLFormElement>) {
event.preventDefault()
setIsLoading(true)
setError(null)
try {
const formData = new FormData(event.currentTarget)
const response = await fetch('/api/submit', { method: 'POST', body: formData })
if (!response.ok) throw new Error('Failed to submit the data. Please try again.')
const data = await response.json()
} catch (error) {
setError(error.message)
} finally {
setIsLoading(false)
}
}
import { z } from 'zod'
const schema = z.object({ /* ... */ })
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const parsed = schema.parse(req.body)
}
required/type é só UX; validação real de segurança precisa acontecer na API Route.response.ok: fetch não rejeita em erro HTTP (4xx/5xx), é preciso checar manualmente e lançar erro.res.redirect(307, path) é o padrão pra navegar após mutação bem-sucedida.