如何将Google reCAPTCHA与react hook表单集成



我以前一直使用react hook表单,让用户以基本形式提交他们的电子邮件地址:

BEFORE:反钩形态,无catpcha

import React from 'react'
import { useForm } from 'react-hook-form'
import { useRouter } from 'next/router'
const MyForm = ({ btnText = 'Join' }) => {
const router = useRouter()
const {
register,
handleSubmit,
formState: { isSubmitted, isSubmitting, isValid, errors },
reset,
} = useForm({
mode: 'onChange',
reValidateMode: 'onChange',
})
const onSubmit = async ({ email }) => {
const response = await fetch('/api/my-endpoint', {
method: 'POST',
body: JSON.stringify({
email: email,
captcha: captchaCode,
}),
headers: {
'Content-Type': 'application/json',
},
})
}

return (
<div tw="">
<form
onSubmit={handleSubmit(onSubmit)}
>

<input
{...register('email', {
required: 'We need an e-mail address',
})}
type="email"
/>
<button
type="submit"
>
Submit
</button>
</form>
</div>
)
}
export default MyForm

现在我刚刚添加了谷歌ReCaptcha v2,但我很难理解如何将其集成到react hoook形式中?

现在:react hook表单+谷歌recatpcha v2

import React from 'react'
import { useForm } from 'react-hook-form'
import ReCAPTCHA from 'react-google-recaptcha'
const MyForm = ({ btnText = 'Join' }) => {
const {
register,
handleSubmit,
formState: { isSubmitted, isSubmitting, isValid, errors },
reset,
} = useForm({
mode: 'onChange',
reValidateMode: 'onChange',
})
const onSubmit = ({ email }) => {
// Execute the reCAPTCHA when the form is submitted
recaptchaRef.current.execute()
}
const onReCAPTCHAChange = async captchaCode => {
// If the reCAPTCHA code is null or undefined indicating that
// the reCAPTCHA was expired then return early
if (!captchaCode) {
return
}
try {
const response = await fetch('/api/my-endpoint', {
method: 'POST',
body: JSON.stringify({
email: email,
captcha: captchaCode,
}),
headers: {
'Content-Type': 'application/json',
},
})
if (response.ok) {
// If the response is ok than show the success alert
alert('Email registered successfully')
} else {
// Else throw an error with the message returned
// from the API
const error = await response.json()
throw new Error(error.message)
}
} catch (error) {
alert(error?.message || 'Something went wrong')
} finally {
// Reset the reCAPTCHA when the request has failed or succeeeded
// so that it can be executed again if user submits another email.
recaptchaRef.current.reset()
reset()
}
}
return (
<form
onSubmit={handleSubmit(onSubmit)}
>
<ReCAPTCHA
ref={recaptchaRef}
size="invisible"
sitekey={process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY}
onChange={onReCAPTCHAChange}
/>
<input
{...register('email', {
required: 'We need an e-mail address',
})}
type="email"
/>
<button
type="submit"
>
Submit
</button>
</form>
)
}
export default MyForm

我的问题:

我似乎很纠结的是,在我使用异步handleSubmit调用之前:

const onSubmit = async ({ email }) => {
const response = await fetch('/api/my-endpoint', {
method: 'POST',
body: JSON.stringify({
email: email,
captcha: captchaCode,
}),
headers: {
'Content-Type': 'application/json',
},
})
}

而现在,onSubmit只是激活了captcha:

const onSubmit = ({ email }) => {
// Execute the reCAPTCHA when the form is submitted
recaptchaRef.current.execute()
}

而我的实际请求现在只在CCD_ 2函数内部提交。在那里,我再也不能访问电子邮件的挂钩形式值了。我怎样才能进入那里?

另外:我的handleSubmit函数现在是同步,所以我不能等待API响应?如何使此异步,但仍能使用react-hook-formrecaptcha?有什么建议吗?

useForm提供了一个getValues()函数来获取表单的值。您可以在组件内部的任何位置使用它。以下是参考资料:https://react-hook-form.com/api/useform/getvalues

const { getValues } = useForm()
const onReCAPTCHAChange = async captchaCode => {
// If the reCAPTCHA code is null or undefined indicating that
// the reCAPTCHA was expired then return early
if (!captchaCode) {
return
}
try {
const values = getValues()
const response = await fetch('/api/my-endpoint', {
method: 'POST',
body: JSON.stringify({
email: values.email,
captcha: captchaCode,
}),
headers: {
'Content-Type': 'application/json',
},
})

}
....
}

或者,您可以在钩子窗体的onSubmit中使用executeAsync而不是execute,然后执行您的请求。

const onSubmit = ({ email }) => {
const token = await recaptchaRef.current.executeAsync();
// You API call here
}

您可以通过调用handleSubmit:返回的函数来用所需的数据调用真正的onSubmit函数

// inside your reCAPTCHA response function
const onSubmitWithFormValues = handleSubmit(
// binding form values to your function and any other params (e.g. token)
(...formSubmitParams) => onSubmit(...formSubmitParams, recaptchaToken)
)
onSubmitWithFormValues()

对于上面的示例,onSubmit签名如下:

const onSubmit = ({ email, password, username }, _ /* unused event */, recaptchaToken: string) => { ... }

最新更新