Errori e fix
Astro: il componente è statico perché manca la client directive
In Astro un componente framework senza `client:*` viene renderizzato in HTML e mai idratato. Il markup c'è, gli eventi no. La direttiva giusta dipende da quando serve l'interattività.
In sintesi
- Senza `client:*` il componente è HTML statico: nessun evento, nessuno stato.
- Scegli la direttiva in base al momento: `client:load` subito, `client:idle` dopo, `client:visible` quando entra in viewport.
- `client:only` richiede il nome del framework e salta del tutto il render sul server.
Risposta breve: senza una direttiva client:*, un componente React, Vue o Svelte dentro Astro viene reso in HTML e mai idratato. Il markup c'è, gli eventi no. Aggiungi la direttiva in base a quando serve l'interattività.
Le direttive
| Direttiva | Quando idrata | Uso tipico |
|---|---|---|
client:load | subito | controlli sopra la piega |
client:idle | quando il browser è libero | interazioni secondarie |
client:visible | quando entra in viewport | sezioni in fondo alla pagina |
client:only | solo nel browser | canvas, editor, API del browser |
Perché l'HTML arriva già finito
Il meccanismo è la compilazione. Astro legge il file .astro a build time e chiede al renderer del framework una stringa HTML. La direttiva client:* è ciò che trasforma quella stringa in un elemento astro-island, con l'URL del componente, quello del renderer e le props serializzate negli attributi. Senza direttiva il nodo esce come HTML puro: nessuno script lo raggiunge, quindi nessun listener viene registrato e nessuno stato esiste. Il componente non è rotto, è una fotografia.
L'esempio
---
import Counter from "../components/Counter.tsx";
---
client:only richiede il nome del framework perché Astro non può dedurlo dal file: senza, la build fallisce.
Come verificarlo
# quante isole contiene davvero l'HTML servito
curl -s http://localhost:4321/ | grep -o "<astro-island" | wc -l
# quali direttive esistono nel sorgente
# (PowerShell: Select-String -Path src/**/*.astro -Pattern "client:")
grep -rn "client:" src --include="*.astro"
Il primo comando conta le isole nell'HTML servito, il secondo trova le direttive nel sorgente. Se il conteggio è zero su una pagina che dovrebbe essere interattiva, la causa è nel sorgente. Se è molto più alto di quanto ti aspetti, il problema è l'opposto e costa byte: una tabella con una direttiva per riga diventa una fila di punti di idratazione.
Cosa non passa attraverso un'isola
Le props devono essere serializzabili. Una funzione passata dal file .astro al componente non attraversa il confine: il componente riceve undefined e l'errore arriva a runtime. Passa dati o definisci il gestore dentro il componente client.
Quando la correzione non funziona
Se aggiungi la direttiva e l'evento continua a non funzionare, controlla la console: un errore di idratazione annulla il mount dell'isola. Un secondo caso è un componente che dipende da un contesto React creato fuori dall'isola: ogni isola è un albero separato, e il provider deve stare dentro.
Attenzione anche al costo: ogni isola porta il runtime del framework. Dieci isole React sulla stessa pagina significano un runtime caricato una volta, ma dieci punti di idratazione da coordinare. Preferisci una sola isola che contiene l'interazione.
Quando la correzione tipica peggiora le cose
La correzione che circola è mettere client:load ovunque qualcosa non risponde. Risolve il sintomo e aggiunge due costi. Astro serializza le props dentro l'attributo dell'isola: una lista di quaranta righe con una direttiva per riga produce quaranta isole e quaranta copie dei dati nel documento, che il browser legge e idrata una per una. Il peso dell'HTML cresce, il tempo prima dell'interattività anche, e il problema di partenza era una sola direttiva mancante.
Il limite di client:visible
Un limite noto di client:visible: l'idratazione dipende da IntersectionObserver. Se l'isola sta dentro un pannello chiuso, un contenitore con altezza zero o un elemento con display:none, non interseca mai il viewport e resta inerte. Non compare un errore, il markup è corretto e il comando non risponde: la diagnosi somiglia di nuovo a una direttiva mancante, e la prima ipotesi sbagliata costa mezz'ora.
Come prevenirlo
- Per default, nessuna direttiva: aggiungila solo dove serve un evento.
- Preferisci
client:visibleper le sezioni sotto la piega. - Verifica nell'HTML la presenza di
astro-islande del chunk del framework. - Una sola isola per area interattiva: se servono dieci direttive per dieci righe, il confine è nel posto sbagliato.
Dove continuare
Nel catalogo: blocco hero, componenti e blocchi. Le guide: struttura App Router e checklist accessibilità; il confronto: peso di una libreria UI.
Domande frequenti
Perché il bottone non risponde al click?
Il componente è stato renderizzato in HTML senza idratazione. Aggiungi la direttiva `client:*` appropriata.
`client:load` e `client:idle` cambiano l'aspetto?
No. Cambiano quando il JavaScript viene eseguito; l'HTML iniziale è lo stesso, salvo componenti che dipendono dall'interattività per il primo paint.
Quando serve `client:only`?
Quando il componente non può essere renderizzato sul server: usa il browser, un canvas o una libreria che accede a `window` all'import.
Perché `client:only` richiede un valore?
Perché Astro non può dedurre il framework dal file in quel caso: scrivi `client:only="react"`.
Come verifico che l'isola sia idratata?
Guarda nell'HTML l'attributo `astro-island` e nel pannello Network il chunk del framework. Se manca il chunk, la direttiva non è stata applicata.