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

ReactJS中登录/注册表单切换时reCAPTCHA渲染异常问题

问题定位与解决方案

问题根源

你遇到的问题本质是React条件渲染导致ReCAPTCHA组件卸载后重新挂载时,无法正确初始化Google reCAPTCHA widget。react-google-recaptcha组件首次挂载时会加载Google的reCAPTCHA脚本并创建widget实例,但当组件被条件渲染卸载后,再次挂载时,由于React的DOM复用机制或组件内部初始化逻辑的限制,无法重新生成有效的widget实例。

解决方案

方案1:给ReCAPTCHA组件添加唯一key属性(推荐)

给两个表单的ReCAPTCHA组件分别设置唯一的key,让React将它们视为独立的组件实例,每次切换时都会重新正确初始化:

修改代码中的ReCAPTCHA部分:

// 登录表单的ReCAPTCHA
<ReCAPTCHA
  sitekey={reCaptchaKey}
  onChange={recaptchaLogin}
  id='login-recaptcha-container'
  key="login-recaptcha" // 添加唯一key
/>

// 注册表单的ReCAPTCHA
<ReCAPTCHA
  sitekey={reCaptchaKey}
  onChange={recaptchaSignup}
  id='signup-recaptcha-container'
  key="signup-recaptcha" // 添加唯一key
/>

方案2:用CSS切换显示/隐藏,避免组件卸载

将条件渲染改为通过CSS控制显示与隐藏,让两个ReCAPTCHA组件始终存在于DOM中,跳过卸载/重新挂载的流程:

修改组件的return部分:

return (
  <div className="login-page-container">
    <CheckLogin />
    {/* 登录表单 - 根据isLoginBlock控制显示 */}
    <div className={`login-block flex flex-col items-center justify-center ${isLoginBlock ? 'block' : 'hidden'}`}>
      <div className="w-full max-w-4xl p-4 bg-white border border-gray-200 rounded-lg shadow-md sm:p-6 md:p-8 dark:bg-gray-800 dark:border-gray-700">
        {/* 登录表单其余代码 */}
        <ReCAPTCHA
          sitekey={reCaptchaKey}
          onChange={recaptchaLogin}
          id='login-recaptcha-container'
        />
        {/* 登录表单其余代码 */}
      </div>
    </div>
    {/* 注册表单 - 根据isLoginBlock控制显示 */}
    <div className={`flex flex-col items-center justify-center mx-3 my-3 ${!isLoginBlock ? 'block' : 'hidden'}`}>
      <div className="w-full max-w-4xl p-4 bg-white border border-gray-200 rounded-lg shadow-md sm:p-6 md:p-8 dark:bg-gray-800 dark:border-gray-700">
        {/* 注册表单其余代码 */}
        <ReCAPTCHA
          sitekey={reCaptchaKey}
          onChange={recaptchaSignup}
          id='signup-recaptcha-container'
        />
        {/* 注册表单其余代码 */}
      </div>
    </div>
  </div>
);

方案3:通过组件引用手动重置ReCAPTCHA

如果前两种方案不适用,可以通过ref获取ReCAPTCHA实例,在切换表单时手动重置widget:

首先添加ref定义和修改切换函数:

import { useState, useRef } from "react";

function LoginSignup() {
  // ... 其余状态定义
  const loginRecaptchaRef = useRef(null);
  const signupRecaptchaRef = useRef(null);

  const toggleLoginSignup = () => {
    setIsLoginBlock(prev => {
      const newState = !prev;
      // 切换时重置对应表单的ReCAPTCHA
      if (newState) {
        signupRecaptchaRef.current?.reset();
      } else {
        loginRecaptchaRef.current?.reset();
      }
      return newState;
    });
  }

  // ... 其余函数定义

然后给ReCAPTCHA组件绑定ref:

// 登录表单的ReCAPTCHA
<ReCAPTCHA
  sitekey={reCaptchaKey}
  onChange={recaptchaLogin}
  id='login-recaptcha-container'
  ref={loginRecaptchaRef}
/>

// 注册表单的ReCAPTCHA
<ReCAPTCHA
  sitekey={reCaptchaKey}
  onChange={recaptchaSignup}
  id='signup-recaptcha-container'
  ref={signupRecaptchaRef}
/>

额外检查点

  • 确认Google reCAPTCHA控制台中已添加当前项目的域名,站点密钥配置正确。
  • 打开浏览器控制台,排查是否存在reCAPTCHA脚本加载失败的错误信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 13:15:51