React-google-recaptcha在Bootstrap模态框中二次打开时不显示
解决Bootstrap模态框中react-google-ReCAPTCHA二次打开不显示的问题
这个问题的核心是:react-google-ReCAPTCHA组件依赖Google的reCAPTCHA脚本初始化DOM元素,当Bootstrap模态框关闭时,组件对应的DOM节点可能被隐藏或销毁,再次打开模态框时,脚本不会自动重新渲染已创建过的reCAPTCHA实例。
下面给几种实用的解决办法:
方法一:控制组件的挂载/卸载
只在模态框打开时渲染ReCAPTCHA,关闭时卸载,确保每次打开都是全新的实例:
- 给模态框绑定状态,比如
isModalOpen,控制模态框显示/隐藏 - 只有当
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方法,确保组件重新渲染:
- 给ReCAPTCHA添加ref,方便调用实例方法
- 监听模态框的
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
相关产品推荐
相关产品推荐

