React
Form actions in SvelteKit: validazione e progressive enhancement
Una form action in SvelteKit valida sul server e restituisce fail() senza ricaricare la pagina. Ecco dove mettere la logica e dove no.
In sintesi
- Una form action vive in +page.server.ts e accetta solo POST con la stessa origine.
- fail(400, dati) restituisce i valori per rimostrare il form senza ricaricare la pagina.
- redirect(303) dopo un POST evita che un refresh ripeta l’invio.
Una form action in SvelteKit è una funzione esportata da +page.server.ts: riceve la richiesta, valida i dati e restituisce fail() o lancia redirect(). Il form funziona anche senza JavaScript, perché resta un POST normale.
L’action minima
import { fail, redirect } from "@sveltejs/kit";
import type { Actions } from "./$types";
export const actions = {
default: async ({ request }) => {
const data = await request.formData();
const email = String(data.get("email") ?? "").trim();
if (!email.includes("@")) {
return fail(400, { email, message: "Email non valida" });
}
await subscribe(email);
throw redirect(303, "/grazie");
},
} satisfies Actions;
Il codice 303 dopo un POST evita che un refresh ripeta l’invio. redirect(307) conserva il metodo, quindi il refresh diventa un secondo POST e l’iscrizione arriva due volte.
Mostrare l’errore senza perdere i dati
import { enhance } from "$app/forms";
let { form } = $props();
Iscriviti
{#if form?.message}{form.message}{/if}
Con use:enhance il POST resta un POST, ma senza ricaricare la pagina. Se togli la direttiva il form continua a funzionare: è questo che rende l’enhancement progressivo e non un requisito.
Dove finisce la validazione
| Punto | Cosa controlla | Cosa non può controllare |
|---|---|---|
| Input nel browser | Formato immediato, attrito minimo | La fiducia: si bypassa |
| Action | Regole di dominio e permessi | Lo stato dell’interfaccia |
| Database | Vincoli e unicità | Il messaggio da mostrare |
La regola è una sola: la validazione che protegge i dati sta nell’action. Il controllo nel browser serve solo alla velocità, e non sostituisce nulla.
Errori frequenti
fail()senza i valori inviati: il form si svuota e l’utente riscrive tutto.redirect()chiamato senzathrow: l’esecuzione continua e la risposta viene inviata due volte.- Action nominata e form che punta a
?/default: il nome non corrisponde e la POST risponde 404. - Campi con un attributo
namediverso dalla chiave letta informData().
Il limite noto
Le form actions hanno bisogno di un server. Con adapter-static non esistono: il form deve chiamare un endpoint esterno o una route API su un’altra origine, e perdi la sessione lato server.
Comandi
npm create svelte@latest my-app
npx svelte-kit sync
Dal catalogo: svelte-bits, flowbite-svelte e il blocco logo Svelte. Le guide: lo store che non si aggiorna e svelte-bits misurata; il confronto: Svelte contro React sui siti di contenuto.
Domande frequenti
Perché il form restituisce 405?
La form action accetta solo POST con la stessa origine. Un link GET verso la pagina o una fetch senza metodo POST produce 405.
Come leggo i dati inviati?
Con request.formData() dentro l’action. Il risultato è un oggetto FormData, quindi ogni valore va convertito in stringa.
A cosa serve il campo form nella pagina?
Contiene ciò che l’action restituisce con fail: serve a rimostrare i valori e il messaggio di errore senza ricaricare la pagina.
Perché redirect non funziona?
redirect va lanciato con throw, oppure restituito come valore. Se lo chiami e lo ignori, l’esecuzione continua e la risposta non viene reindirizzata.
Funziona con più form nella stessa pagina?
Sì, con action nominate: ogni form punta a un nome dopo la barra e la action esporta la chiave con lo stesso nome.