在尝试不重定向已提交表单的用户后,我在将表单发送到我的表单服务时遇到了问题。
我设置了一个 Formspark 表单以在framer.com 上使用。 Framer.com 强迫我使用我不知道的 Typescript(我现在只知道 HTML CSS 和 JS)。我从 Formspark 的文档和 sitepoint 社区收集了一些想法和随机信息。如果有人创造一些空闲时间来帮助解决我的问题,我真的(真的)很感激。
TL;DR,跳到解决方案
所有问题都与我的表单的提交操作有关。基本上,主要问题是我没有在 Formspark 期望我的表单具有的“const response = ...”内添加正确的标头(Content-type 和 Accept),这有点尴尬。第二个问题(这不是我面临的问题,但最终将要面对的问题)是我没有将 formData 用作普通对象,也没有将其字符串化。最后的问题是,如果响应正常,则不使用 const 值来重置(),如果不使用 const 来表示 currentTarget,则会抛出错误。
这是我的表格(简化):
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.log("Initializing hCaptcha...")
if (window.hcaptcha) {
window.hcaptcha.render(captchaRef.current!, {
sitekey: "mycaptchacode",
callback: (token: string) => {
console.log("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.log("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" />
。一直拖着我来到这里的最主要的事情就是无法保持在同一页面上。我不希望用户被重定向。我非常感谢您的帮助。
它应该是这样的:
/* 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.log("Form Data: ", formDataObject)
try {
const response = await fetch("https://submit-form.com/DhrCyMyaP", {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify(formDataObject),
})
console.log({ response })
const responseData = await response.json()
console.log({ 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.*/
非常感谢先生。最大
据我所知,它应该可以工作,前端逻辑似乎没问题。我认为您需要检查您发布的网址。有几点需要注意
防止重定向所需要做的就是在提交事件上调用
preventDefault
。所以你有 event.preventDefault()
并且效果很好。
至于其余的,我无法复制你的错误,
"Failed to fetch"
。我在 https://replit.com/@maxmezzomo/Form-Submit 上用你的代码进行了重复。我刚刚删除了验证码的提前返回和警报,我认为这也不是问题。
但是,您发布到 https://submit-form.com/formid 会返回 404,并显示消息“此表单不再存在”。即使在浏览器中,单击链接也会得到该结果。所以这是我想说的预期行为。但它与
failed to fetch
内联。我只是认为如果你想发帖,你需要有一个 id,所以类似于 https://submit-form.com/<formid>
,其中 formid 是你想要发帖的地方。
一旦您拥有指向服务器所需网址的网址,您就应该能够发出请求。在 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的期望,但你可以研究一下。
我用这个更新了replit,似乎有效,获得200。
现在响应的代码为200,因此表单数据已成功提交。但是代码的一部分仍然会抛出一个错误,稍后会被捕获,在处理事件后您不能使用事件 currentTarget,我不知道它到底是如何工作的,但可能是因为在您处理事件时它是异步的请求 currentTarget 的响应为 null。因此,简单的方法是在发出请求之前创建对目标的引用
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
const target = event.currentTarget;
event.preventDefault()
if (!token) {...
然后你可以使用该变量来调用重置。
现在 UI 也应该显示表单已成功提交!