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

React-google-recaptcha在Bootstrap模态框中二次打开时不显示

解决Bootstrap模态框中react-google-ReCAPTCHA二次打开不显示的问题

这个问题的核心是:react-google-ReCAPTCHA组件依赖Google的reCAPTCHA脚本初始化DOM元素,当Bootstrap模态框关闭时,组件对应的DOM节点可能被隐藏或销毁,再次打开模态框时,脚本不会自动重新渲染已创建过的reCAPTCHA实例。

下面给几种实用的解决办法:

方法一:控制组件的挂载/卸载

只在模态框打开时渲染ReCAPTCHA,关闭时卸载,确保每次打开都是全新的实例:

  1. 给模态框绑定状态,比如isModalOpen,控制模态框显示/隐藏
  2. 只有当isModalOpen为true时,才渲染ReCAPTCHA组件

代码示例:

import { useState } from 'react';
import ReCAPTCHA from 'react-google-recaptcha';

function YourModalComponent() {
  const [isModalOpen, setIsModalOpen] = useState(false);

  return (
    <>
      <button onClick={() => setIsModalOpen(true)}>打开模态框</button>
      
      <div className={`modal ${isModalOpen ? 'show d-block' : ''}`} tabIndex="-1">
        <div className="modal-dialog">
          <div className="modal-content">
            <div className="modal-body">
              {/* 只有模态框打开时才渲染组件 */}
              {isModalOpen && (
                <ReCAPTCHA
                  sitekey={process.env.REACT_APP_EMAIL_RECAPTCHA_SITE_KEY}
                  className="g-recaptcha-response"
                  name="g-recaptcha-response"
                />
              )}
            </div>
            <div className="modal-footer">
              <button onClick={() => setIsModalOpen(false)}>关闭</button>
            </div>
          </div>
        </div>
      </div>
    </>
  );
}

方法二:利用Bootstrap模态框事件触发组件重置

通过Bootstrap的shown.bs.modal事件,在模态框完全显示后,调用ReCAPTCHA组件的reset方法,确保组件重新渲染:

  1. 给ReCAPTCHA添加ref,方便调用实例方法
  2. 监听模态框的shown.bs.modal事件,触发时重置组件

代码示例:

import { useRef, useEffect } from 'react';
import ReCAPTCHA from 'react-google-recaptcha';

function YourModalComponent() {
  const recaptchaRef = useRef(null);
  const modalRef = useRef(null);

  useEffect(() => {
    const modalElement = modalRef.current;
    const handleModalShown = () => {
      // 重置reCAPTCHA实例
      if (recaptchaRef.current) {
        recaptchaRef.current.reset();
      }
    };

    // 添加事件监听
    modalElement.addEventListener('shown.bs.modal', handleModalShown);
    
    // 清理事件监听
    return () => {
      modalElement.removeEventListener('shown.bs.modal', handleModalShown);
    };
  }, []);

  return (
    <>
      <button data-bs-toggle="modal" data-bs-target="#exampleModal">打开模态框</button>
      
      <div ref={modalRef} className="modal" id="exampleModal" tabIndex="-1">
        <div className="modal-dialog">
          <div className="modal-content">
            <div className="modal-body">
              <ReCAPTCHA
                ref={recaptchaRef}
                sitekey={process.env.REACT_APP_EMAIL_RECAPTCHA_SITE_KEY}
                className="g-recaptcha-response"
                name="g-recaptcha-response"
              />
            </div>
          </div>
        </div>
      </div>
    </>
  );
}

方法三:强制组件重新渲染

通过修改组件的key属性,每次模态框打开时改变key,让React认为是新组件,从而重新初始化:

import { useState } from 'react';
import ReCAPTCHA from 'react-google-recaptcha';

function YourModalComponent() {
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [recaptchaKey, setRecaptchaKey] = useState(Date.now());

  const handleOpenModal = () => {
    setRecaptchaKey(Date.now()); // 打开时更新key
    setIsModalOpen(true);
  };

  return (
    <>
      <button onClick={handleOpenModal}>打开模态框</button>
      
      <div className={`modal ${isModalOpen ? 'show d-block' : ''}`} tabIndex="-1">
        <div className="modal-dialog">
          <div className="modal-content">
            <div className="modal-body">
              <ReCAPTCHA
                key={recaptchaKey} // 用key强制重新渲染
                sitekey={process.env.REACT_APP_EMAIL_RECAPTCHA_SITE_KEY}
                className="g-recaptcha-response"
                name="g-recaptcha-response"
              />
            </div>
            <div className="modal-footer">
              <button onClick={() => setIsModalOpen(false)}>关闭</button>
            </div>
          </div>
        </div>
      </div>
    </>
  );
}

这三种方法里,方法一最直接,每次打开模态框都重新创建组件实例,完全避免重复初始化问题;方法二更适合需要保留组件状态的场景;方法三是React中强制重新渲染的通用技巧,简单易实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 04:20:57