Что я пытаюсь сделать:
На своем сайте я создал регистрационную форму, при отправке которой я хочу выполнить два действия:
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(); работает, чтобы прервать операцию отправки формы, если она выполняется перед асинхронной функцией / ожиданием, поэтому я предполагаю, что это проблема времени, необходимого для выполнения операции подписки.
Может ли кто-нибудь пролить свет на то, что здесь происходит, и на потенциальное решение?




Можете ли вы 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,
});
}
}
Возможно, в этом примере он нам больше не нужен (потому что мы сразу сохраняем то, что нам нужно из события). Однако, если вы обнаружите, что вам все еще нужен доступ к событию после возврата вашего асинхронного кода, я думаю, вам нужно будет сохранить его. Я не эксперт, так что прочитайте это reactjs.org/docs/events.html
Большое спасибо @ksav, ты чертова легенда! Это кажется таким простым, но это решение ускользнуло от меня, когда я пытался исправить это самостоятельно. Я заметил, что вы используете
event.persist()в начале вашего submitHandler в вашем codeandbox. Есть ли причина, по которой вы пропустили это в своем ответе здесь? Это необходимо?