# Ritardo all'invio o invii doppi

> Formspree Docs · Risoluzione dei problemi · 11 aprile 2024

Se hai cliccato su "invia" su un modulo HTML qualsiasi, probabilmente hai vissuto quel momento di incertezza che precede il reindirizzamento alla pagina di ringraziamento. Anche se dura solo pochi istanti, può far sorgere molte domande come "il modulo non funziona?", "il mio clic è stato registrato?" o persino "internet non funziona?". A volte gli utenti, presi dal panico, finiscono per cliccare di nuovo sul pulsante di invio, generando invii duplicati.

Il ritardo crea un'esperienza utente sgradevole. Inoltre, un secondo clic comporta una richiesta duplicata al tuo modulo Formspree (che viene conteggiata nella tua quota di utilizzo) e un record duplicato nel tuo elenco di invii (che dovrai ripulire in seguito). Ecco perché abbiamo preparato questa breve guida per aiutarti a capire perché ciò accade e come puoi risolverlo con un breve snippet JS.

## **Perché succede?**

Il ritardo che i tuoi utenti percepiscono dopo aver cliccato sul pulsante "invia" di un modulo Formspree non è causato da un problema di Formspree stesso; è una conseguenza naturale del funzionamento dei moduli web. Ecco una rapida panoramica del processo: quando un utente clicca sul pulsante "invia", il browser avvia una richiesta HTTP verso il backend con i dati del modulo. Questa richiesta attraversa internet per raggiungere il backend e durante questo tragitto può incontrare latenza dovuta a connessioni di rete lente.

Una volta che la richiesta raggiunge i server, deve essere elaborata. Ciò può comportare la convalida delle informazioni, la loro memorizzazione nel database e, potenzialmente, l'invio di email di conferma. Anche questa elaborazione richiede tempo, anche se tipicamente inferiore al trasferimento di rete. Una volta completata, il backend risponde con una conferma e reindirizza l'utente alla pagina di ringraziamento.

Il tempo impiegato dalla richiesta per viaggiare da e verso il server causa un ritardo lato utente dopo il clic sul pulsante "invia". Inoltre, connessioni più lente come le reti di dati mobili possono aggiungere latenza alla richiesta e accentuare il problema.

Ecco come si presenta il ritardo:

![9Yt3xqi.gif](/images/zendesk/55d2857f77082f83.gif)

## **Come puoi risolverlo?**

Anche se non puoi fare nulla riguardo al tempo impiegato dalla richiesta HTTP, puoi però offrire una migliore esperienza di attesa ai tuoi utenti. Se stai sviluppando un progetto basato su React (o Next/Gatsby), puoi sfruttare l'oggetto `state` restituito dall'hook `useForm` della [libreria React di Formspree](/articles/working-with-react/the-formspree-react-library/) per sapere se il modulo è attualmente in fase di invio e disabilitare il pulsante di invio. Tuttavia, in JS puro, devi implementare questo controllo da solo.

Per farlo, devi ascoltare l'[evento submit del modulo](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit_event), che viene attivato ogni volta che un modulo viene inviato in una pagina web. Una volta ricevuto questo evento, devi disabilitare il pulsante di invio e/o mostrare un elemento dell'interfaccia (come uno spinner) per informare l'utente che i dati del modulo sono in fase di elaborazione in background.

> NOTA: Sebbene tu possa implementare la stessa logica usando anche un [evento click](https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event) sul pulsante "invia", l'evento "submit" sul modulo è un modo più affidabile per catturare tutti i possibili modi di inviare il modulo, che includono il clic sul pulsante "invia", la pressione di `Enter` durante la modifica di un campo e l'invio programmatico del modulo chiamando il metodo `form.requestSubmit()`.

### **Disabilita il pulsante all'invio**

Il modo più semplice per informare l'utente sull'elaborazione in background è disabilitare il pulsante di invio e, facoltativamente, mostrare un segnale di attesa sul cursore quando si passa sopra il pulsante. Ecco come apparirebbe:

![VueV1eF.gif](/images/zendesk/04905806e773197c.gif)

Per implementarlo, dovrai impostare uno sfondo grigio e il cursore `wait` per lo stato disabilitato del pulsante tramite CSS. Successivamente, devi ascoltare l'evento `submit` sul modulo HTML e impostare l'attributo `disabled` del pulsante di invio su `true` quando l'evento `submit` viene rilevato.

Ecco come apparirebbe il file HTML:

```html
<html>

<head>
    <style>
        /* Other styles omitted... */
        
        /* 1. Set the background and cursor for the disabled state of the button */
        #submitButton:disabled {
            cursor: wait;
            background: #dfdfdf;
        }

    </style>
</head>

<body>
    <form id="contact-form" name="simple-contact-form" accept-charset="utf-8" action="https://formspree.io/f/{form_id}"
        method="post">
        <label for="full-name">Full Name</label>
        <input type="text" name="name" id="full-name" placeholder="First and Last" required="">
        <label for="email-address">Email Address</label>
        <input type="email" name="_replyto" id="email-address" placeholder="email@domain.tld" required="">
        <label for="message">Message</label>
        <textarea rows="5" name="message" id="message"
            placeholder="Your message here"
            required=""></textarea>
        <input id="submitButton" type="submit" value="Submit">
    </form>

    <!-- 2. Add the following script to listen to the submit event -->
    <script>
        const form = document.getElementById('contact-form');
        const submitButton = document.getElementById('submitButton');
	
	
        form.addEventListener('submit', function (event) {
	
            // Sets the submit button's disabled attribute as true
            submitButton.disabled = true;
        });
    </script>
</body>

</html>
```

Questo metodo è semplice e sfrutta i cursori di caricamento nativi delle varie piattaforme. Per esempio, ecco come apparirebbe il cursore di caricamento a un utente Windows:

![mUg5eOm.gif](/images/zendesk/ecc14008d606e832.gif)

Il cursore non è visibile sui dispositivi mobili. Tuttavia, il pulsante di invio appare comunque grigio, così l'utente sa che il suo tocco è stato registrato e non può toccare una seconda volta:

![fU5hbNa.gif](/images/zendesk/221f83b7ee10da1b.gif)

### **Sostituisci il pulsante con un altro elemento dell'interfaccia all'invio**

In alternativa, potresti nascondere completamente il pulsante di invio e mostrare al suo posto un elemento dell'interfaccia come uno spinner quando un modulo viene inviato:

![Vi8x3Oc.gif](/images/zendesk/0fa8ce7db3c32b21.gif)

Anche il codice per questo modulo è piuttosto semplice:

```html
<html>

<head>
    <style>
        /* 1. Add the following styles */
        #loader-container {
            width: 100%;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
        }

        #loader {
            border: 4px solid #e5122e; 
            border-bottom: 4px solid #fff;
            border-radius: 50%;
            width: 16px;
            height: 16px;
            animation: spin 1s linear infinite;
        }
          
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
    </style>
</head>

<body>
    <form id="contact-form" name="simple-contact-form" accept-charset="utf-8" action="<https://formspree.io/f/{form_id}>"
        method="post">
        <fieldset id="fs-frm-inputs">
            <div id="inputs">
                <label for="full-name">Full Name</label>
                <input type="text" name="name" id="full-name" placeholder="First and Last" required="">
                <label for="email-address">Email Address</label>
                <input type="email" name="_replyto" id="email-address" placeholder="email@domain.tld" required="">
                <label for="message">Message</label>
                <textarea rows="5" name="message" id="message"
                    placeholder="Your message here"
                    required=""></textarea>
                <input type="hidden" name="_subject" id="email-subject" value="Contact Form Submission">
            </div>
        </fieldset>
        <input id="submitButton" type="submit" value="Submit">
        
        <!-- 2. Add the following div tags -->
        <div id="loader-container" >
            <div id="loader" hidden="hidden"></div>
        </div>
        
    </form>

	<!-- 3. Add the following script to listen to the submit event -->
	<script>
	    const form = document.getElementById('contact-form');
	    const submitButton = document.getElementById('submitButton');
	    const loader = document.getElementById('loader')
	
	
	    form.addEventListener('submit', function (event) {
	    
	        // Removes the hidden attribute from the loader element
	        loader.hidden = ""
	        
	        // Sets the submit button to be hidden
	        submitButton.hidden = "hidden";
	    });
	</script>
</body>

</html>
```

Aggiungi due `<div>`, uno annidato nell'altro, subito sotto il pulsante di invio, aggiungi il CSS per centrare il loader all'interno del contenitore e imposta i keyframe per l'animazione del loader. Infine, aggiungi lo script JS che ascolta l'evento submit del modulo e nasconde il pulsante di invio mentre rende visibile il loader.

Questo approccio ti dà maggiore controllo sul design dell'interfaccia dell'elemento loader. Inoltre, puoi mantenere un design coerente del loader su tutte le piattaforme.

> Lo script per aggiungere il listener dell'evento submit del modulo deve accedere al DOM HTML per impostare il listener. Quindi, devi assicurarti che il codice per aggiungere il listener dell'evento submit del modulo `(form.addEventListener('submit', function (event) {})` venga eseguito solo dopo che il DOM ha terminato il caricamento. Ciò significa che se stai usando uno script inline, assicurati di aggiungerlo subito prima del tag di chiusura `</body>`, proprio come negli esempi mostrati sopra. In alternativa, se stai usando uno script esterno, assicurati di posticiparne (`defer`) l'esecuzione fino a dopo l'analisi del DOM HTML usando l'attributo defer nel tag `<script>`, oppure di ascoltare l'evento `DOMContentLoaded` nello script prima di aggiungere il listener dell'evento submit del modulo al documento.

## **Offrire un'esperienza utente fluida con i tuoi moduli**

Come hai visto, il problema del ritardo nel feedback dopo il clic sul pulsante di invio e gli episodi di invii duplicati possono essere facilmente risolti implementando elementi dell'interfaccia che informano l'utente sull'elaborazione in background eseguita per gestire l'invio del modulo. Speriamo che questa guida ti abbia aiutato a capire come funziona dietro le quinte e ti abbia fornito alcuni snippet di codice utili per iniziare subito.
