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

Next.js中React Modal关闭后ReCAPTCHA无法重置问题求助

解决Next.js中react-modal里ReCAPTCHA重复打开不显示的问题

核心问题分析

你遇到的问题本质是ReCAPTCHA组件在模态框关闭时被卸载/从DOM移除,导致ref丢失,后续重新打开时无法正确初始化;另外Next.js的SSR特性也会影响依赖浏览器环境的ReCAPTCHA加载。

具体解决方案

1. 动态导入ReCAPTCHA并禁用SSR

react-google-recaptcha依赖浏览器的window对象,直接在SSR环境中导入会报错,用Next.js的动态导入禁用SSR:

import dynamic from 'next/dynamic';
const ReCAPTCHA = dynamic(() => import('react-google-recaptcha'), {
  ssr: false,
  loading: () => <div>加载验证码...</div>
});

2. 条件渲染ReCAPTCHA组件

不要让ReCAPTCHA一直存在于DOM中,仅在模态框打开时渲染,确保每次打开模态框都能重新初始化组件:

import { useState, useRef, useEffect } from 'react';
import Modal from 'react-modal';

// 必须设置,满足无障碍要求
Modal.setAppElement('#__next');

export default function ReportJobModal() {
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [reportReason, setReportReason] = useState('');
  const recaptchaRef = useRef(null);

  // 模态框打开时重置ReCAPTCHA
  useEffect(() => {
    if (isModalOpen && recaptchaRef.current) {
      recaptchaRef.current.reset();
    }
  }, [isModalOpen]);

  const handleSubmit = (e) => {
    e.preventDefault();
    const captchaToken = recaptchaRef.current?.getValue();
    
    if (!captchaToken) {
      alert('请完成验证码验证');
      return;
    }

    // 这里写你的表单提交逻辑
    console.log('举报原因:', reportReason, '验证码:', captchaToken);
    
    // 提交后重置状态并关闭模态框
    setReportReason('');
    setIsModalOpen(false);
  };

  return (
    <>
      <button onClick={() => setIsModalOpen(true)}>Report Job</button>
      <Modal
        isOpen={isModalOpen}
        onRequestClose={() => setIsModalOpen(false)}
        contentLabel="举报职位表单"
      >
        <h3>举报该职位</h3>
        <form onSubmit={handleSubmit}>
          <div>
            <label>举报原因:</label>
            <textarea
              value={reportReason}
              onChange={(e) => setReportReason(e.target.value)}
              required
              rows="4"
            />
          </div>
          
          {/* 仅在模态框打开时渲染ReCAPTCHA */}
          {isModalOpen && (
            <ReCAPTCHA
              ref={recaptchaRef}
              sitekey="你的ReCAPTCHA Site Key"
              size="normal"
            />
          )}

          <div style={{ marginTop: '1rem', display: 'flex', gap: '1rem' }}>
            <button type="submit">提交举报</button>
            <button type="button" onClick={() => setIsModalOpen(false)}>取消</button>
          </div>
        </form>
      </Modal>
    </>
  );
}

3. 关键注意点

  • 不要在模态框关闭时保留ReCAPTCHA组件:模态框隐藏时,react-modal会把内容从DOM移除,导致ReCAPTCHA实例被销毁,ref自然变为null。
  • 依赖useEffect监听模态框状态:只有当模态框打开、ReCAPTCHA组件完成渲染后,recaptchaRef.current才会有值,此时调用reset()才能生效。
  • 确保Site Key配置正确:检查你的ReCAPTCHA Site Key是否绑定了当前域名,否则会加载失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 02:55:13