Выполнение асинхронной функции перед отправкой формы

Что я пытаюсь сделать:

На своем сайте я создал регистрационную форму, при отправке которой я хочу выполнить два действия:

1) Подпишите пользователя на список EDM MailChimp (используя только поля Имя, Электронная почта).

2) Сохраните полную форму в Netlify, выполнив действие POST (все поля, особенно их сообщения)

Вот моя форма:

<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>

А вот мой обработчик onSubmit:

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,
    });
  }
}

Что тут происходит:

Как вы можете видеть в фрагментах кода, для достижения этого я пытаюсь сначала асинхронно подписать пользователя на MailChimp с полями, которые они отправили, и если я не получаю сообщение об успешном завершении, я прерываю операцию отправки с помощью event.preventDefault();.

В качестве бонуса это также полезно для предотвращения повторных регистраций, так как я получу ответ от MailChimp, если они уже находятся в списке подписчиков.

Проблема:

Однако на практике происходит то, что форма отправляется и перенаправляется на страницу успеха (/thank-you/) независимо от того, завершилась ли операция подписки, была ли она успешной или неудачной.

У меня около 50% отправок форм приводят к подписке на MailChimp, а другая половина — нет. Когда я тестирую это на своей стороне, иногда я вижу мигание сообщения об успешной/неудачной подписке непосредственно перед тем, как страница перенаправляется на страницу успеха (/thank-you/).

Стоит отметить, что event.preventDefault(); работает, чтобы прервать операцию отправки формы, если она выполняется перед асинхронной функцией / ожиданием, поэтому я предполагаю, что это проблема времени, необходимого для выполнения операции подписки.

Может ли кто-нибудь пролить свет на то, что здесь происходит, и на потенциальное решение?

JS - События опций формы
JS - События опций формы
В продолжение предыдущей статьи CSS - стили, связанные с вводом формы , в этой статье мы будем использовать JS для взаимодействия с формами, на этот...
CSS - Стили, связанные с вводом формы
CSS - Стили, связанные с вводом формы
Общими стилями ввода для форм являются Input (включая Text, Radio, checkbox), Select и Textarea, из которых Input относительно прост, поэтому в этой...
Создание многостраничной формы заявления о приеме на работу с помощью Angular
Создание многостраничной формы заявления о приеме на работу с помощью Angular
Наличие на корпоративном сайте форм заявлений о приеме на работу, или "трудовых анкет", экономит время и деньги как для соискателей, так и для...
2
0
1 276
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Можете ли вы preventDefault перед await, а затем вызвать submit() в форме после того, как вы получите успех от асинхронного вызова 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,
    });
  }
}

пример рабочих кодовandbox

Большое спасибо @ksav, ты чертова легенда! Это кажется таким простым, но это решение ускользнуло от меня, когда я пытался исправить это самостоятельно. Я заметил, что вы используете event.persist() в начале вашего submitHandler в вашем codeandbox. Есть ли причина, по которой вы пропустили это в своем ответе здесь? Это необходимо?

Allan of Sydney 21.07.2019 03:34

Возможно, в этом примере он нам больше не нужен (потому что мы сразу сохраняем то, что нам нужно из события). Однако, если вы обнаружите, что вам все еще нужен доступ к событию после возврата вашего асинхронного кода, я думаю, вам нужно будет сохранить его. Я не эксперт, так что прочитайте это reactjs.org/docs/events.html

ksav 21.07.2019 10:26

Другие вопросы по теме