繁体   English   中英

如何将 Google reCAPTCHA 与 react-hook-form 集成?

[英]How to Integrate Google reCAPTCHA with react-hook-form?

我之前一直在使用react-hook-form,让用户以基本形式提交他们的email地址:

之前:react-hook-form,没有 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

现在我刚刚添加了 google ReCaptcha v2,但我很难理解如何将它集成到 react-hoook-form 中?

现在:react-hook-form + google 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只是激活验证码:

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

...我的实际请求现在仅在onReCAPTCHAChange function 内提交。在那里,我无法再访问 email 的 react-hook-form 值。 我怎样才能在那里获得访问权限?

另外:我的handleSubmit function 现在是同步的,所以我不能等待 API 响应? 我怎样才能使这个异步,但仍然可以使用react-hook-formrecaptcha 有什么建议吗?

useForm提供了一个getValues() function 来获取表单的值。 您可以在组件内部的任何位置使用它。 这是参考: 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',
        },
      })
     
    }
    ....
}

或者,您可以使用executeAsync而不是在钩子表单的onSubmitexecute ,然后执行您的请求。

const onSubmit = ({ email }) => {
    const token = await recaptchaRef.current.executeAsync();

    // You API call here
}

您可以通过调用handleSubmit返回的 function 来使用您需要的数据调用您的真实onSubmit handleSubmit

// 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) => { ... }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM