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

Next.js中react-google-recaptcha切换视图后无法渲染的解决方法

解决Next.js多步骤表单中react-google-recaptcha二次渲染失败问题

问题场景

在Next.js多步骤表单中使用react-google-recaptcha组件时遇到以下问题:

  • 首次进入包含ReCAPTCHA的视图(View3),组件正常加载
  • 用户点击「返回」按钮,视图切换导致ReCAPTCHA组件被卸载
  • 再次点击「下一步」回到View3时,ReCAPTCHA无法渲染

核心原因

react-google-recaptcha依赖Google官方的reCAPTCHA脚本,组件卸载时该脚本不会自动完成清理与重新初始化流程;二次挂载时,旧实例的残留会阻止新组件正常渲染。

解决方案

方案1:给ReCAPTCHA组件加唯一key强制重新挂载

通过给组件分配动态变化的key,让React每次进入View3时都创建全新的ReCAPTCHA实例,彻底绕开旧实例残留问题。

修改方式1:在View3内部给ReCAPTCHA加key

const View3 = ({onBack}) => {
  const recaptchaRef = useRef(null)
  // 生成唯一key,基于时间戳确保每次挂载都不同
  const recaptchaKey = useRef(Date.now()).current

  const onReCAPTCHAChange = (captchaCode) => {
    if(!captchaCode) return
    console.log(captchaCode)
  }

  return (
    <div className="p-4 rounded bg-gray-100">
      <div>View 3</div>
      <div>
      <ReCAPTCHA
        ref={recaptchaRef}
        key={recaptchaKey} // 添加动态key
        size="compact"
        sitekey={process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY}
        onChange={onReCAPTCHAChange}
        badge="inline"
      />
      </div>
      <div className="flex items-center gap-4">
        <button className="btn-primary" onClick={onBack}>Back</button>
      </div>
    </div>
  )
}

修改方式2:在父组件中给View3加key

export default function Sandbox() {
  const [view, setView] = useState(1)
  // 每次切换到View3时生成新key
  const view3Key = view === 3 ? Date.now() : undefined

  return (
    <div>
      {view===1 ? <View1 onNext={()=>setView(2)} /> :
       view===2 ? <View2 onNext={()=>setView(3)} onBack={()=>setView(1)} /> :
       view===3 ? <View3 key={view3Key} onBack={()=>setView(2)} /> : null
      }
    </div>
  )
}

方案2:手动控制ReCAPTCHA的重置与销毁

利用组件的ref,在卸载时调用reset()方法清理实例,确保下次挂载时能正常初始化:

const View3 = ({onBack}) => {
  const recaptchaRef = useRef(null)

  const onReCAPTCHAChange = (captchaCode) => {
    if(!captchaCode) return
    console.log(captchaCode)
  }

  useEffect(() => {
    // 组件卸载时重置ReCAPTCHA
    return () => {
      if (recaptchaRef.current) {
        recaptchaRef.current.reset()
      }
    }
  }, [])

  return (
    <div className="p-4 rounded bg-gray-100">
      <div>View 3</div>
      <div>
      <ReCAPTCHA
        ref={recaptchaRef}
        size="compact"
        sitekey={process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY}
        onChange={onReCAPTCHAChange}
        badge="inline"
      />
      </div>
      <div className="flex items-center gap-4">
        <button className="btn-primary" onClick={onBack}>Back</button>
      </div>
    </div>
  )
}

方案3:动态导入ReCAPTCHA并禁用SSR

Next.js的SSR可能导致reCAPTCHA脚本加载异常,通过动态导入组件并禁用SSR,确保组件仅在客户端渲染:

// 在使用ReCAPTCHA的文件中动态导入
import dynamic from 'next/dynamic'

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

// 后续组件使用方式不变
const View3 = ({onBack}) => {
  // ... 原有代码
}

推荐方案

优先选择方案1,操作简单且能彻底解决问题,不需要额外处理生命周期或脚本加载逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 21:25:30