React中添加EmailJS reCaptcha验证提交表单报错如何解决
报错根因
当前代码触发报错的核心问题有两个:
- 调用EmailJS的
send方法时,最后一个参数错误传入了固定字符串g-recaptcha-response。该参数位置需要传入用户完成reCAPTCHA校验后动态生成的响应令牌,而非固定字段名 - 未监听、存储reCAPTCHA组件返回的校验结果,也没有在表单提交前校验用户是否完成人机验证,直接发起接口请求就会被EmailJS的校验规则拦截
具体实现步骤
- 新增独立state存储reCAPTCHA返回的动态校验令牌
- 给ReCAPTCHA组件绑定
onChange回调,用户完成校验后自动将返回的令牌存入state - 表单提交逻辑里增加前置判断:如果没拿到有效令牌就阻断提交,提示用户先完成人机验证
- 调用EmailJS发送方法时,将存储的动态令牌作为最后一个参数传入
- 发送成功/失败后重置reCAPTCHA组件状态,避免令牌过期导致下次提交失败
修正后的代码
组件核心逻辑
import { useState } from 'react'; import ReCAPTCHA from "react-google-recaptcha"; import { send } from '@emailjs/browser'; function Register() { const [open, setOpen] = useState(false); // 新增state存储reCAPTCHA校验令牌 const [recaptchaToken, setRecaptchaToken] = useState(null); const [toSend, setToSend] = useState({ azienda: '', email: '', piva: '', codicefiscale: '', }); // 监听reCAPTCHA校验结果 const handleRecaptchaChange = (token) => { setRecaptchaToken(token); }; const handleSubmit=(e)=>{ e.preventDefault(); // 前置校验:未完成人机验证直接阻断 if (!recaptchaToken) { alert('请先完成人机验证'); return; } send( 'service_****', 'template_*****', toSend, '************', recaptchaToken // 传入动态获取的校验令牌 ) .then((response) => { setOpen(true); // 重置reCAPTCHA状态 window.grecaptcha.reset(); setRecaptchaToken(null); }) .catch((err) => { console.error('提交失败:', err); // 校验失败也重置状态 window.grecaptcha.reset(); setRecaptchaToken(null); }) }; const handleChange = (e) => { setToSend({...toSend, [e.target.name]: e.target.value }); }; // 其余组件渲染逻辑
表单内ReCAPTCHA组件配置
<ReCAPTCHA sitekey='**********' onChange={handleRecaptchaChange} />
注意事项
- 提前确认EmailJS后台对应服务已经开启reCAPTCHA v2校验,且后台配置的站点密钥、私钥和前端代码里的sitekey完全匹配
- reCAPTCHA v2令牌默认有效期为2分钟,令牌过期时组件会自动触发onChange返回null,前置校验逻辑会自动拦截过期提交,无需额外处理
- 如果使用reCAPTCHA v3版本,逻辑基本一致,只需要在提交时主动调用
grecaptcha.execute方法获取令牌,再传给EmailJS即可
内容的提问来源于stack exchange,提问作者Adele
相关产品推荐
相关产品推荐

