如何在最新react-hook-form中正确集成react-hook-recaptcha?
解决
react-hook-recaptcha 与最新 react-hook-form 集成问题 关键修复点:
- 补全缺失类型:定义
Newsletter接口,解决类型报错 - 正确初始化reCAPTCHA:使用
useRecaptcha钩子加载并管理验证码实例 - 移除冗余状态:删除
contact状态,直接用react-hook-form的表单状态管理 - 整合验证逻辑:提交表单前先执行reCAPTCHA验证,通过后再处理业务逻辑
修改后的完整代码:
"use client" import { useCallback, useEffect, useState } from "react" import { useForm, SubmitHandler, FormEvent } 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" // 补全缺失的类型定义 interface Newsletter { email: string } const Newsletter = () => { const [isSubmitted, setIsSubmitted] = useState<boolean>(false) const [recaptchaError, setRecaptchaError] = useState<string>("") const sitekey = "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI" // 替换为你的实际站点密钥 const containerId = "test-recaptcha" 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" }) // 初始化reCAPTCHA const { execute, resetRecaptcha, token } = useRecaptcha({ sitekey, containerId, // 可选:配置验证码主题、大小等 // theme: "dark", // size: "compact" }) // 移除冗余的contact状态,直接用react-hook-form管理 const handleInputChange = (e: FormEvent<HTMLInputElement>) => { clearErrors("email") setRecaptchaError("") } const onSubmit: SubmitHandler<Newsletter> = useCallback(async (data) => { try { // 执行reCAPTCHA验证 const recaptchaToken = await execute() if (!recaptchaToken) { setRecaptchaError("Voer de reCAPTCHA-verificatie in") return } // 这里添加你的实际提交逻辑,比如调用API,带上recaptchaToken console.log("表单数据:", data) console.log("reCAPTCHA Token:", recaptchaToken) setIsSubmitted(true) reset() resetRecaptcha() // 重置验证码 } catch (error) { setRecaptchaError("reCAPTCHA-verificatie mislukt, probeer opnieuw") } }, [execute, reset, resetRecaptcha]) const onFormValidate = useCallback(() => { if (errors.email || recaptchaError) { setIsSubmitted(false) } if (isSubmitSuccessful) { setIsSubmitted(true) } }, [errors, isSubmitSuccessful, recaptchaError]) 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} 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> )} {recaptchaError && ( <p className="text-xs font-bold text-red-800"> {recaptchaError} </p> )} {isSubmitted && ( <Alert type="success" message={`Bedankt voor het aanmelden van ons nieuwsbrief`} /> )} <div id={containerId} className="mt-4" /> </form> </div> </div> ) } export default Newsletter
核心说明:
useRecaptcha初始化:传入站点密钥和容器ID后,钩子会自动加载reCAPTCHA脚本并渲染验证码组件- 提交验证:在
onSubmit中先调用execute()触发验证码验证,拿到有效token后再执行后续提交逻辑 - 状态清理:提交成功后调用
resetRecaptcha()重置验证码,方便用户再次提交 - 冗余状态移除:
react-hook-form已经提供了完整的表单状态管理,不需要额外维护contact状态,避免状态不一致问题
内容的提问来源于stack exchange,提问作者Galanthus
相关产品推荐
相关产品推荐

