typescript react-hook-form与Google recaptcha

uubf1zoe  于 2023-10-22  发布在  TypeScript
关注(0)|答案(1)|浏览(139)

我已经安装了react-hook-recaptcha软件包以将其添加到我的新闻稿表单中。然而,从示例来看,代码似乎已经过时了,复制/粘贴示例代码部分会导致未定义的变量和函数。关于如何使用最新的react-hook-form实现它,Google上没有太多信息。
我已经导入了useRecaptcha函数和2个常量,一个用于siteKey,另一个用于横幅应该附加的ID。
这是我的代码,但我不知道如何使它工作,因为没有太多关于如何做到这一点的信息。

"use client"

import { useCallback, useEffect, useState } from "react"

import { useForm, SubmitHandler } from "react-hook-form"

import { useRecaptcha } from "react-hook-recaptcha"

import { cn } from "@/lib/utils"

import { z, ZodType } from "zod"

import Alert from "./Alert"
import Button from "./Button"
import { zodResolver } from "@hookform/resolvers/zod"

const Newsletter = () => {
  const [isSubmitted, setIsSubmitted] = useState<boolean>(false)
  const [contact, setContact] = useState<Newsletter>({
    email: ""
  })

  const sitekey = "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI" // change to your site key
  const containerId = "test-recaptcha" // this id can be customized

  const schema: ZodType<Newsletter> = z.object({
    email: z.string().email({ message: "Ongeldig e-mailadres" })
  })

  const {
    register,
    handleSubmit,
    reset,
    clearErrors,
    formState: { errors, isSubmitSuccessful }
  } = useForm<Newsletter>({
    resolver: zodResolver(schema),
    reValidateMode: "onSubmit"
  })

  const handleInputChange = (e: FormEvent) => {
    setContact({
      ...contact,
      [e.currentTarget.name]: e.currentTarget.value
    })

    clearErrors("email")
  }

  const onSubmit: SubmitHandler<Newsletter> = useCallback((data) => {
    return new Promise<void>((resolve) => {
      resolve()

      setIsSubmitted(true)
    })
  }, [])

  const onFormValidate = useCallback(() => {
    if (errors.email) {
      setIsSubmitted(false)
    }

    if (isSubmitSuccessful) {
      setIsSubmitted(true)

      reset({
        email: ""
      })

      setContact({
        email: ""
      })
    }
  }, [errors, isSubmitSuccessful, reset])

  useEffect(() => {
    onFormValidate()
  }, [onFormValidate])

  const email = register("email")

  return (
    <div className="text-midnight bg-accent sm:rounded-2xl">
      <div className="flex flex-col flex-wrap content-center justify-center pt-6 pb-12 mx-auto md:py-12">
        <h2 className="text-3xl leading-none text-center sm:text-5xl lg:text-6xl font-playfair">
          Stay in the loop!
        </h2>

        <p className="max-w-lg pt-4 pb-8 mx-auto text-center text-md">
          Houd ons in de gaten, misschien staan we binnenkort bij jou in de
          buurt of op een festival!
        </p>

        <form
          autoComplete="off"
          className="space-y-3"
          onSubmit={handleSubmit(onSubmit)}
        >
          <div className="flex flex-col sm:flex-row">
            <input
              {...email}
              onChange={handleInputChange}
              value={contact.email}
              className={cn(
                errors.email
                  ? "placeholder:text-red-800 border-red-800"
                  : "placeholder:text-midnight border-midnight",
                "flex-grow p-3 bg-white border-1 text-sm md:text-base outline-none rounded-tl-lg rounded-tr-lg sm:rounded-tr-none sm:rounded-br-none sm:rounded-l-lg text-midnight placeholder:text-midnight focus:outline-none"
              )}
              placeholder="e-mailadres..."
            />

            <Button
              buttonType="submit"
              text="Versturen"
              buttonClass="btn-secondary border-2 rounded-tl-none rounded-tr-none sm:rounded-tr-lg sm:rounded-bl-none px-7 rounded-lg"
            />
          </div>

          {errors.email && (
            <p className="text-xs font-bold text-red-800">
              {errors.email.message}
            </p>
          )}

          {isSubmitted && (
            <Alert
              type="success"
              message={`Bedankt voor het aanmelden van ons nieuwsbrief`}
            />
          )}
         <div id={containerId} />
        </form>
      </div>
    </div>
  )
}

export default Newsletter
k7fdbhmy

k7fdbhmy1#

我已经安装了react-google-recaptcha@types/react-google-recaptcha
我还没有找到将react-hook-form方法扩展到google的reCAPTCHA组件中的方法。
因此,我使用reCAPTCHA onChange方法将值设置为setValue()方法的useForm字段。
见下文:

import React, { useEffect, useRef } from 'react'
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import ReCAPTCHA from 'react-google-recaptcha'
import PopupModal from './PopupModal'
import { newsletterFormData, newsletterFormSchema } from '../models/validationFormModel'

type PopupNewsletterProps = {
  email: string,
  isOpen: boolean,
  onSubmit: (message: string) => void,
  onClose: () => void
}

// https://blog.logrocket.com/creating-reusable-pop-up-modal-react/
const PopupNewsletter: React.FC<PopupNewsletterProps> = ({email, isOpen, onSubmit, onClose}) => {

  const btnRef = useRef<HTMLButtonElement>(null)
  const reRef = useRef<ReCAPTCHA>(null)
  const {register, handleSubmit, formState: {errors}, setValue, setFocus, resetField} = useForm<newsletterFormData>({
    resolver: zodResolver(newsletterFormSchema)
  })

  useEffect(() => {
    if (isOpen) {
      setValue("email", email)
      resetField("nome")
      if (reRef.current) reRef.current.reset()
      setTimeout(() => {
        setFocus("nome")
      }, 0)
      
    }
  }, [isOpen])

  const handleSubscription = async (payload: newsletterFormData) => {
    
    if (btnRef.current) {
      btnRef.current.textContent = "Aguarde..."
      btnRef.current.disabled = true
    }
    const response = await fetch("/api/newsletter", {
      method: "POST",
      headers: new Headers({
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      }),
      body: JSON.stringify(payload)
    })
    const {message} = await response.json()
    if (btnRef.current) {
      btnRef.current.textContent = "Inscrever"
      btnRef.current.disabled = false
    }
    onSubmit(message)
  }

  return (
    <PopupModal
      hasCloseBtn={true}
      isOpen={isOpen} 
      onClose={onClose}
    >
      <form className='flex flex-col gap-2' onSubmit={handleSubmit(handleSubscription)}>
        <div className='border-2 p-2 rounded-md'>
          <label htmlFor="name">Digite seu primeiro nome</label>
          <div>
            <span className='px-2 bg-slate-400'></span>
            <input className="px-1 bg-text-wraper outline-none" id='name' maxLength={15} type="text" {...register("nome")} />
          </div>
          {errors.nome && <span className='text-sm text-red-500'>{errors.nome.message}</span>}
        </div>

        <div className='border-2 p-2 rounded-md'>
          <label htmlFor="email">Seu melhor e-mail</label>
          <div>
            <span className='px-2 bg-slate-400'></span>
            <input className="px-1 bg-text-wraper outline-none" id='email' type="email" {...register("email")} />
          </div>
          {errors.email && <span className='text-sm text-red-500'>{errors.email.message}</span>}
        </div>

        <div>
          <ReCAPTCHA sitekey='YOUR-SITE-KEY' ref={reRef} onChange={(token) => setValue("token", token || "")} />
          {errors.token && <span className='text-sm text-red-500'>{errors.token.message}</span>}
        </div>

        <button className='text-white w-full h-fit py-2 px-4 md:w-fit md:self-end bg-btn-wraper hover:bg-btn-hover' type='submit' ref={btnRef}>Inscrever</button>
      </form>
    </PopupModal>
  )
}

export default PopupNewsletter

我希望它能帮助

相关问题