После попытки не перенаправить пользователя, отправившего форму, у меня возникли проблемы с отправкой формы в службу форм.
Я настраиваю форму Formspark для использования на сайтеframer.com. Framer.com заставляет меня использовать Typescript, о котором я не знаю (сейчас я знаю только HTML, CSS и JS). Я собрал идеи и случайную информацию из документации Formspark и сообщества Sitepoint. Я был бы очень (действительно) признателен, если бы кто-нибудь нашел немного свободного времени, чтобы помочь решить мою проблему.
Вот моя форма (упрощенная):
import React, { useEffect, useRef, useState } from "react"
import styled from "styled-components"
const SalesForm = styled.form`
/*styles*/
`
const FormInput = styled.input`
/*styles*/
`
const Button = styled.button`
/*styles*/
`
const SuccessMessage = styled.div`
/*styles*/
`
const ErrorMessage = styled.div`
/*styles*/
`
export default function Form(props) {
const captchaRef = useRef<HTMLDivElement>(null)
const [token, setToken] = useState<string | null>(null)
const [message, setMessage] = useState<string | null>(null)
const [isSuccess, setIsSuccess] = useState<boolean | null>(null)
useEffect(() => {
console.info("Initializing hCaptcha...")
if (window.hcaptcha) {
window.hcaptcha.render(captchaRef.current!, {
sitekey: "mycaptchacode",
callback: (token: string) => {
console.info("hCaptcha token generated:", token)
setToken(token)
},
})
}
}, [])
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault()
if (!token) {
alert("Please verify that you are human.")
return
}
const formData = new FormData(event.currentTarget)
console.info("Form Data: ", Array.from(formData.entries()))
try {
const response = await fetch("https://submit-form.com/formid", {
method: "POST",
body: formData,
})
if (response.ok) {
setMessage("Form successfully submitted!")
setIsSuccess(true)
event.currentTarget.reset()
} else {
const errorText = await response.text()
console.error("Error response: ", errorText)
setMessage(
"There was a problem with your submission: " + errorText
)
setIsSuccess(false)
}
} catch (error) {
console.error("Submission error: ", error)
setMessage(
"There was an error submitting the form: " + error.message
)
setIsSuccess(false)
}
}
return (
<SalesForm id = "sales-form" onSubmit = {handleSubmit}>
<script src = "https://js.hcaptcha.com/1/api.js" async defer></script>
<FormInput type = "text" id = "comp-name" name = "comp-name" placeholder = "comp-name" required/>
<div ref = {captchaRef}></div>
<Button type = "submit">Send</Button>
{message &&
(isSuccess ? (
<SuccessMessage>{message}</SuccessMessage>
) : (
<ErrorMessage>{message}</ErrorMessage>
))}
</SalesForm>
)
}
Хочу дать немного больше информации:
<input type = "hidden" name = "_redirect" value = "redirecturl.com" />
. Не оставаться на той же странице было главным, что затащило меня сюда. Я не хочу, чтобы пользователь был перенаправлен.Я был бы очень признателен за вашу помощь.
Насколько я могу судить, это должно работать, логика интерфейса кажется в порядке. Я думаю, вам нужно проверить URL-адрес, по которому вы публикуете. Несколько вещей, на которые стоит обратить внимание
Все, что вам нужно, чтобы предотвратить перенаправление, — это вызвать preventDefault
при событии отправки. Итак, у вас есть event.preventDefault()
, и это отлично работает.
В остальном мне не удалось повторить вашу ошибку, "Failed to fetch"
. Я сделал повтор с вашим кодом на https://replit.com/@maxmezzomo/Form-Submit. Я просто удалил ранний возврат и оповещение о капче, тоже не думаю, что в этом проблема.
Однако вы отправляете сообщение на https://submit-form.com/formid, который возвращает 404 с сообщением «Эта форма больше не существует». Даже из браузера вы получите то же самое, если щелкнете ссылку. Я бы сказал, что это ожидаемое поведение. Но это встроено в failed to fetch
. Я просто думаю, что вам действительно нужен идентификатор, если вы хотите публиковать сообщения, например https://submit-form.com/<formid>
, где formid — это место, где вы хотите публиковать сообщения.
Если у вас есть URL-адрес, указывающий на URL-адрес, ожидаемый сервером, вы сможете сделать свой запрос. Кажется, что в Formspark конечная точка ожидает следующие заголовки https://documentation.formspark.io/examples/ajax.html#axios-with-recaptcha-v2.
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
как только вы добавите их, я думаю, это должно сработать, вы, вероятно, захотите, чтобы полезная нагрузка также была json, чтобы вы могли сделать что-то вроде
JSON.stringify(Object.fromEntries(Object.entries(formData)))
который должен предоставить json объекта с данными формы, то, что вам понадобится, зависит от того, чего ожидает API, но вы можете это изучить.
Обновил реплит этим, вроде работает, получаю 200.
Итак, теперь ответ имеет код 200, что означает, что данные формы были успешно отправлены. Но есть часть кода, которая все еще выдает ошибку, которая обнаруживается позже. Вы не можете использовать событие currentTarget после обработки события. Я не знаю, как именно оно работает, но, вероятно, поскольку оно асинхронно к моменту обработки события. ответ на запрос currentTarget имеет значение null. Поэтому простой способ — создать ссылку на цель, прежде чем делать запрос.
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
const target = event.currentTarget;
event.preventDefault()
if (!token) {...
затем вы можете использовать эту переменную для вызова сброса.
Теперь пользовательский интерфейс также должен показывать, что форма успешно отправлена!
да, окей, круто, спасибо, с фактическим идентификатором возвращается 302. Итак, я вижу упомянутую вами ошибку. Глядя на документацию formpark, хотя ему нужны данные в формате json и с соответствующими заголовками json, я обновлю ответ, как только добавлю заголовки, я получу 200. Что касается капчи, по крайней мере, при повторении, я просто закомментировал эти строки, поэтому он отправляется
эй, чувак, спасибо тебе большое, что помог мне до сих пор. Вы можете очистить все строки, касающиеся капчи, и использовать «submit-form.com/DhrCyMyaP», потому что эта форма не требует капчи, я сделал ее в пробных целях.
да, конечно, пожалуйста. Спасибо за создание новой формы, похоже, она работает, по крайней мере, в части http. Сейчас единственная проблема, которую я вижу, — это вызов сброса для currentTarget, который имеет значение null. Я обновлю ответ, чтобы объяснить это.
Эй, чувак, пользовательский интерфейс показывает, что форма отправлена. А также «ответ: Ответ {тип: 'cors', URL: 'submit-form.com/aDAJt6OP', перенаправлен: ложь, статус: 200, ок: правда,…}». НО теперь Formspark не получает форму. Дайте мне знать, если вы хотите узнать что-нибудь еще. Кстати, я еще раз протестировал форму, и форма все еще работает без кода, который удерживает пользователя на странице. Однако, чтобы не проявлять неуважения к вашим усилиям, большое вам спасибо. Я тоже все перепроверю.
ЭВРИКА! Что я изменил: я добавил «const responseData = await response.json(); console.info({ResponseData });» эти строки дали мне данные ответа, а данные ответа были пустыми ( "{"responseData": {}}" ). Исправление: я создал новую константу, чтобы сделать formData простым объектом: formDataObject = Object.fromEntries(formData.entries()). Я установил formDataObject для преобразования в строку следующим образом: «body: JSON.stringify(formDataObject)». На этот раз моя форма была отправлена в Formspark! Пожалуйста, отредактируйте свой ответ соответствующим образом, большое спасибо за вашу помощь.
Приятно, приятно слышать, что это сработало!
Все проблемы были связаны с действием моей формы при отправке. По сути, основная проблема заключалась в том, что я не добавил правильные заголовки (Content-type и Accept) внутри «const response = ...», которые Formspark ожидал от моей формы, что немного смущает. Вторая проблема (с которой я не столкнулся, но в конечном итоге столкнулась с ней) заключается в том, что я не использовал formData как простой объект, а также не строкировал его. И последняя проблема заключалась в том, чтобы не использовать константное значение для сброса(), если ответ был в порядке, и если вы не используете константу для представления currentTarget, это приведет к ошибке.
Вот как это должно было выглядеть:
/* Other lines of code that have remained unchanged.*/
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
const target = event.currentTarget
event.preventDefault()
if (!token) {
// You don't need to include this if you are not using captcha
// alert("Please verify that you are human.")
// return
}
const formData = new FormData(event.currentTarget)
const formDataObject = Object.fromEntries(formData.entries())
console.info("Form Data: ", formDataObject)
try {
const response = await fetch("https://submit-form.com/form-id", {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify(formDataObject),
})
console.info({ response })
const responseData = await response.json()
console.info({ responseData })
if (response.ok) {
setMessage("Form successfully submitted!")
setIsSuccess(true)
target.reset()
} else {
const errorText = await response.text()
console.error("Error response: ", errorText)
setMessage(
"There was a problem with your submission: " + errorText
)
setIsSuccess(false)
}
} catch (error) {
console.error("Submission error: ", error)
setMessage(
"There was an error submitting the form: " + error.message
)
setIsSuccess(false)
}
}
/* Other lines of code that have remained unchanged.*/
Большое спасибо Мистеру Максу
Эй, спасибо за ответ! Я использую там настоящий «формид». Используйте submit-form.com/aDAJt6OP . Если вы не используете hcaptcha, форма не будет отправлена.