You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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组件的状态更新连锁反应导致的:

  1. GoogleReCaptcha完成验证后调用onVerify,执行setToken(token)触发组件重渲染
  2. 组件重渲染时,GoogleReCaptcha检测到refreshReCaptcha属性(哪怕值未变化),会再次触发验证流程
  3. 验证完成又调用onVerify更新token,循环往复

修复步骤

  1. 给onVerify添加条件更新逻辑,避免无意义的token更新触发重渲染:
const onVerify = useCallback((newToken) => {
  // 仅当新token与当前token不同时才更新
  if (newToken !== token) {
    setToken(newToken);
  }
}, [token]); // 依赖数组加入token,确保回调能获取最新状态
  1. 修正表单验证逻辑,避免错误提示被无条件清除:
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);
      });
  });
};
  1. 确保GoogleReCaptchaProvider稳定渲染:你的代码中已经将其放在组件最外层,无需调整,避免将其放在会频繁重渲染的子组件中。

内容的提问来源于stack exchange,提问作者Chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 06:03:20