formsgatsbynetlify

Performing an async function before form post submission


What I'm Trying To Do:

On my site I've created a registration form that I'd like to perform two actions upon submission:

  1. Subscribe the user to a MailChimp EDM list (using just the Name, Email fields).

  2. Store the complete form in Netlify by performing a POST action (all fields, particularly their messages)

Here's my form:

<form
  className={`contact-form ${submitError ? 'has-error' : ''}`}
  name={formName}
  method="POST"
  onSubmit={event => this.submitHandler(event)}
  action="/thank-you/"
  data-netlify="true"
  data-netlify-honeypot="bot-field"
>
   // Form fields
</form>

And here's my onSubmit handler:

submitHandler = async (event) => {
  const {
    email,
    fieldValues,
    submitting,
  } = this.state;
  if (submitting) return false;
  this.setState({
    submitting: true,
    submitError: false,
  });
  const result = await addToMailchimp(email, fieldValues);
  if (result.result === 'success') {
    // Inconsequential, as success should result in redirection to the success page
    this.setState({
      submitting: false,
    });
  } else {
    event.preventDefault(); // this SHOULD stop form submit?
    this.setState({
      errorMessage: decodeEntities(result.msg),
      submitError: true,
      submitting: false,
    });
  }
}

What's Happening Here:

As you can see in the code snippets, in order to achieve this I am attempting to first asynchronously subscribe the user to MailChimp with the fields they have submitted, and if I don't get a success message I break the submit operation with event.preventDefault();.

As a bonus, this is also useful for preventing repeat registrations, as I'll get a message back from MailChimp if they're already on the subscribe list.

The Issue:

However, what happens in the wild is that the form submits and redirects to the success page (/thank-you/) regardless of whether the subscribe operation finishes, is successful or unsuccessful.

I've got about 50% of form submissions resulting in MailChimp subscriptions, and the other half not. When I'm testing this on my end, sometimes I see a blink of the subscribe success / failure message just before the page redirects to the success page (/thank-you/).

It's worthwhile noting event.preventDefault(); works to break the form submit operation if it's executed at before the asynchronous / await function - so I'm guessing it's an issue with the time it takes to perform a subscribe operation.

Can anyone shed any light on what's happening here and a potential solution?


Solution

  • Can you preventDefault before the await, and then call submit() on the form after you get a success from the async call to addToMailchimp?

    submitHandler = async (event) => {
      event.preventDefault()
      const form = e.target
    
      const {
        email,
        fieldValues,
        submitting,
      } = this.state;
      if (submitting) return false;
      this.setState({
        submitting: true,
        submitError: false,
      });
      const result = await addToMailchimp(email, fieldValues);
      if (result.result === 'success') {
        // Inconsequential, as success should result in redirection to the success page
        this.setState({
          submitting: false,
        });
        form.submit()
      } else {
    
        this.setState({
          errorMessage: decodeEntities(result.msg),
          submitError: true,
          submitting: false,
        });
      }
    }
    

    working codesandbox example