react-google-recaptcha-v3在React组件中频繁发请求原因排查
问题描述
我使用react-google-recaptcha-v3包时,提交表单能正常获取Google reCAPTCHA v3评分,但在Chrome网络面板发现未提交表单就出现无限循环的reCAPTCHA请求,每秒多次发送到https://www.google.com/recaptcha/api2/reload?k=xxxx(xxxx为我的reCAPTCHA站点密钥)。这显然不符合预期,请问是我的React组件导致的吗?
精简后的组件代码
import React, { useState, useCallback } from 'react' import config from 'config' import { GoogleReCaptchaProvider, GoogleReCaptcha } from "react-google-recaptcha-v3" function ContactForm(props) { /*form data*/ const [name, setName] = useState('') /*validation state*/ const [noNameError, setNoNameError] = useState(false) /*recaptcha state*/ const [token, setToken] = useState(); const [refreshReCaptcha, setRefreshReCaptcha] = useState(false); const key = config.RECAPTCHA_V3_SITEKEY const onVerify = useCallback((token) => { setToken(token); }); const getIP = async()=>{ const response = await fetch('https://geolocation-db.com/json/'); const data = await response.json(); return(data.IPv4) } const handleSubmit = (event) => { event.preventDefault() if(!doValidationStuff()){ setNoNameError(true) } setNoNameError(false) const userIpGetter = getIP() userIpGetter.then(function(ipResult){ myService.doStuff( name, token, ipResult ) .then(()=>{ doOtherStuff() setRefreshReCaptcha(r => !r) }) }) } const setFormName = (event)=>{ setName(event.target.value) } return ( <GoogleReCaptchaProvider reCaptchaKey={key}> <form id="contactForm" onSubmit={handleSubmit} className="needs-validation"> <GoogleReCaptcha action='ContactForm' onVerify={onVerify} refreshReCaptcha={refreshReCaptcha} /> <div className="mb-3"> <label className="form-label">Name</label> <input className="form-control" type="text" placeholder="Name" value={name} onChange={setFormName}/> <span style={{ color: "red", display: noNameError ? 'block' : 'none' }}>Please enter your name.</span> </div> <div className="d-grid"> <button className="btn btn-primary btn-lg" type="submit">Submit</button> </div> </form> </GoogleReCaptchaProvider> ) } export { ContactForm };
问题原因及修复方案
核心原因
无限请求循环是由GoogleReCaptcha组件的状态更新连锁反应导致的:
GoogleReCaptcha完成验证后调用onVerify,执行setToken(token)触发组件重渲染- 组件重渲染时,
GoogleReCaptcha检测到refreshReCaptcha属性(哪怕值未变化),会再次触发验证流程 - 验证完成又调用
onVerify更新token,循环往复
修复步骤
- 给
onVerify添加条件更新逻辑,避免无意义的token更新触发重渲染:
const onVerify = useCallback((newToken) => { // 仅当新token与当前token不同时才更新 if (newToken !== token) { setToken(newToken); } }, [token]); // 依赖数组加入token,确保回调能获取最新状态
- 修正表单验证逻辑,避免错误提示被无条件清除:
const handleSubmit = (event) => { event.preventDefault(); const isValid = doValidationStuff(); // 根据验证结果设置错误状态 setNoNameError(!isValid); // 验证不通过直接返回,不执行后续逻辑 if (!isValid) return; getIP().then(ipResult => { myService.doStuff(name, token, ipResult) .then(() => { doOtherStuff(); setRefreshReCaptcha(r => !r); }); }); };
- 确保
GoogleReCaptchaProvider稳定渲染:你的代码中已经将其放在组件最外层,无需调整,避免将其放在会频繁重渲染的子组件中。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

