React
Autofill che rompe il form
L'autofill rompe il form quando il browser scrive nel campo senza evento React: lo stato resta vuoto, il campo sembra pieno e il submit invia niente.
In sintesi
- Il browser compila i campi prima che React ascolti gli eventi.
- I token di autoComplete vengono dalla specifica HTML del WHATWG.
- La correzione robusta è non controllare i campi che il browser compila.
L'autofill rompe il form quando il browser scrive nel campo senza emettere un evento React: lo stato resta vuoto, il campo sembra pieno e il submit invia niente.
Perché lo stato resta indietro
Il browser compila i campi prima che React sia pronto ad ascoltare gli eventi. Con un campo controllato il testo visibile arriva dal browser, mentre la variabile dello stato è ancora una stringa vuota: le due copie non si parlano.
Email
Continue
I token di autoComplete vengono dalla specifica HTML del WHATWG: email, given-name e one-time-code sono valori riconosciuti, mentre un token inventato viene ignorato dal browser.
La correzione: lasciare il valore nel DOM
function LoginForm() {
async function onSubmit(event: React.FormEvent) {
event.preventDefault();
const data = new FormData(event.currentTarget);
await fetch("/api/login", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(Object.fromEntries(data.entries())),
});
}
return (
Email
Password
Continue
);
}
Nessun useState: il campo non ha una seconda copia da tenere allineata, quindi quello che l’autofill ha scritto è l’unica copia esistente. FormData legge il DOM al submit e non dipende da un evento che potrebbe non arrivare.
I tre sintomi
- Campo visivamente pieno, stato vuoto: la validazione dice che il campo è obbligatorio anche se il testo si vede.
- Password non aggiornata: il gestore compila due campi e solo uno arriva al submit.
- Doppio valore: dopo il primo tasto il valore del browser e quello dello stato si sovrascrivono a vicenda.
- Leggere il campo con
useEffectal mount: il gestore di password scrive dopo, la lettura restituisce stringa vuota e il bug sembra un problema di React.
Riprodurre il caso
npx playwright codegen http://localhost:5173
Con il registratore si compila il form a mano e si riproduce l'invio; Playwright, licenza Apache-2.0, conserva i passaggi e li riesegue, così la correzione va verificata su ogni browser e non solo su quello di sviluppo.
La regola di decisione
Regola: lascia al DOM i campi che il browser conosce, email, current-password, street-address, one-time-code, e controlla solo quelli che costruisci tu, come uno slider o un selettore di date. Il segnale è la provenienza del valore: se può arrivare da fuori, il DOM è la fonte; se nasce da un gesto dentro l’app, lo stato va bene.
La verifica non finisce con un test verde: Chrome, Safari e Firefox scrivono nel campo in momenti diversi e con eventi diversi. Un test Playwright che usa fill() non riproduce l’autofill, perché emette gli stessi eventi di un utente; serve un profilo con credenziali salvate oppure una registrazione manuale dello schermo.
React ricrea i nodi quando cambia la key di un form: un contatore come key azzera il DOM e con esso quello che il gestore aveva scritto. Tieni la key stabile, oppure passa a defaultValue il valore che deve sopravvivere a un remount. In sviluppo StrictMode monta il componente due volte e rende il sintomo più frequente: non lo crea, ma lo mostra. Se il form vive dentro una scheda che si smonta, lo stesso effetto torna anche in produzione.
Record vivi nel catalogo
Tre form di accesso da confrontare: login-form, sign-in-form e login-01. Per sfogliare per categoria parti da blocchi login.
La limitazione
Non esiste un evento standard per l'autofill: input arriva nella maggior parte dei browser, ma non in tutti e non sempre. La correzione robusta è lasciare non controllati i campi che il browser compila, oppure leggere il valore dal DOM al submit.
Dove continuare
Il confronto fra i due schemi è in form controllati e non; il valore del campo è in ref, DOM e stato; le librerie misurate sono in librerie form React.
Domande frequenti
Posso disattivare l'autofill?
In parte. autoComplete uguale off è ignorato da quasi tutti i browser, quindi la strada giusta è convivere con l'autofill, non spegnerlo.
Perché solo la password resta vuota?
Il gestore compila i campi in ordine e alcuni browser emettono l'evento per il primo e non per il secondo. Va letto il valore dal DOM al submit.
Un campo non controllato risolve il problema?
Sì, perché il valore vive nel DOM e il submit lo legge con FormData. Perdi la validazione immediata, che torna al momento dell'invio.
Il problema esiste anche con react-hook-form?
Meno, perché i campi sono non controllati e il valore si legge al submit. Resta da gestire il primo render e i campi dipendenti.
Come lo testo senza compilare a mano?
Con Playwright si riproduce l'invio e si riesegue il test dopo la correzione, così la verifica resta ripetibile.