React
Le runes di Svelte 5: stato, derivati ed effetti
Le runes sostituiscono le assegnazioni magiche di Svelte 4: state per lo stato, derived per i calcoli, effect solo per il DOM e le API esterne.
In sintesi
- Le runes sono chiamate che il compilatore riconosce: funzionano solo in .svelte e .svelte.ts.
- Un valore calcolato va in $derived, non in $effect: l’effetto serve per ciò che sta fuori dal componente.
- $state avvolge oggetti in un proxy; $state.raw serve per dati grandi che sostituisci in blocco.
In Svelte 5 lo stato si dichiara con $state: la rune è una chiamata che il compilatore riconosce, non un let di cui indovina il ruolo. Da quella chiamata il compilatore sa cosa tracciare e cosa lasciare fermo.
Quattro runes coprono quasi tutto
$state per lo stato mutabile, $derived per i valori calcolati, $effect per gli effetti collaterali, $props per gli input del componente. $bindable, $inspect e $host servono in casi più stretti.
npx sv migrate svelte-5
let { start = 0 }: { start?: number } = $props();
let count = $state(start);
const double = $derived(count * 2);
(count += 1)}>Add one
{count} × 2 = {double}
$state avvolge oggetti e array in un proxy: le modifiche annidate sono tracciate. Per dati grandi che sostituisci in blocco c’è $state.raw; per passare un oggetto a una libreria esterna usa $state.snapshot, che restituisce una copia semplice.
Derived non è un effetto
$derived dichiara un valore, $derived.by accetta un blocco di codice. $effect gira dopo l’aggiornamento del DOM, solo nel browser, e serve per il DOM o per API esterne: usarlo per allineare due stati produce un ciclo che il compilatore non ti segnala.
let query = $state("");
let items = $state([]);
const matches = $derived.by(() =>
items.filter((item) => item.name.toLowerCase().includes(query.toLowerCase())),
);
$effect(() => {
document.title = matches.length + " results";
});
Props con $props e $bindable
let { title, value = 0 } = $props() dichiara gli input e i loro default. $bindable() rende una prop scrivibile da fuori: senza, l’assegnazione resta locale al figlio e il genitore non vede il cambio.
| Runa | Scopo | Errore tipico |
|---|---|---|
| $state | Stato mutabile locale | Dichiararla in un .ts senza il suffisso .svelte |
| $derived | Valore calcolato | Assegnarle un valore: è in sola lettura |
| $effect | Effetti dopo il DOM | Sincronizzare due stati, che vuole un derivato |
| $props | Input del componente | Leggere una prop senza default e trovare un valore vuoto |
Il limite da mettere in conto
Le runes esistono solo dove il compilatore le vede: nei file .svelte e in quelli con suffisso .svelte.ts. Un modulo .ts normale non può contenere $state, e $effect non gira durante il rendering sul server.
Errori che si vedono nella migrazione
- Mescolare la sintassi vecchia e le runes nello stesso componente: in un componente con runes
export letnon è ammesso. - Scrivere dentro un
$derived: il valore è in sola lettura e l’errore arriva a runtime. - Usare
$effectper sincronizzare due stati: serve un$derived, l’effetto aggiunge un ciclo. - Leggere uno stato dopo un
awaitdentro un effetto e aspettarsi che venga tracciato: la dipendenza va letta prima della pausa.
I componenti Svelte del catalogo sono già in questa forma: flowbite-svelte e svelte-bits si installano come sorgente, e il blocco form mostra il caso in cui lo stato locale basta. Il routing è in routing e layout in SvelteKit, il vecchio modello di store in store che non si aggiorna, il confronto in Svelte vs React.
Domande frequenti
Devo riscrivere tutti i componenti?
No. La modalità runes si attiva per componente e Svelte 5 compila ancora la sintassi vecchia. Riscrivi dove lo stato diventa difficile da seguire, non tutto in una volta.
$state o $state.raw?
$state per strutture che modifichi in profondità, raw per array e oggetti grandi che sostituisci in blocco. Raw non traccia le modifiche interne: riassegna il valore.
Perché $effect gira più volte?
Perché il primo giro registra le dipendenze e i successivi applicano il risultato. Se i giri sono troppi, l’effetto legge e scrive lo stesso stato: sposta il calcolo in un derivato.
Le runes funzionano in un file .ts?
Solo con il suffisso .svelte.ts, che passa dal compilatore. Un file .ts normale non viene processato e la rune resta una chiamata a una funzione che non esiste.
Svelte 5 è compatibile con le librerie Svelte 4?
In gran parte sì: i componenti vecchi continuano a compilare in modalità legacy. Il rischio sono le azioni che dipendono da this e i binding impliciti, che nelle runes non esistono più.