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

PuntoCosa controllaCosa non può controllare
Input nel browserFormato immediato, attrito minimoLa fiducia: si bypassa
ActionRegole di dominio e permessiLo stato dell’interfaccia
DatabaseVincoli 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 senza throw: 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 name diverso dalla chiave letta in formData().

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.