Next.js中Firebase OTP验证出现RecaptchaVerifier销毁错误的原因与解决
解决'RecaptchaVerifier instance has been destroyed'错误
你遇到的问题根源在于handleSubmit里调用了window.recaptchaVerifier.clear()——这个方法会彻底销毁RecaptchaVerifier实例,而非仅重置验证状态。当不刷新页面重新进入表单时,window.recaptchaVerifier变量虽仍存在,但指向的实例已被销毁,后续调用render()或reset()自然触发报错。
方案1:替换clear()为reset(),保留实例可用性
将handleSubmit中的clear()改为reset(),后者仅重置验证码状态,不会销毁实例,确保下次使用时实例仍有效。
修改后的handleSubmit代码:
const handleSubmit = async (otp: any) => { try { setLoading(true); if (otp) { const confirmOtp = await otpInfo.confirmResult.confirm(otp); if (confirmOtp) { toast.success('Phone number verified successfully!'); setOtpInfo((prev: any) => ({ ...prev, otpVerified: true })); // 用reset替代clear,不销毁实例 window.recaptchaVerifier.reset(); closeModalHandler(); } } else { toast.error('Invalid OTP'); } } catch (error) { toast.error('Invalid OTP please try again'); } finally { setLoading(false); } };
方案2:增加实例有效性检查,失效时重新创建
若需在特定场景销毁实例(如用户切换表单类型),可在verifyPhoneNumber中先检查实例可用性,失效则重新创建:
修改后的verifyPhoneNumber代码:
const verifyPhoneNumber = async () => { setVerifyNumberLoader(true); if (otpInfo.otpVerified) return; try { // 检查实例是否存在且未被销毁 if (!window.recaptchaVerifier || window.recaptchaVerifier['grecaptcha'] === null) { // 清理旧实例(如果存在) if (window.recaptchaVerifier) { window.recaptchaVerifier.clear(); } // 创建新实例 window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier( "recaptcha-container", { size: "invisible", }, ); } await window.recaptchaVerifier.render(); const appVerifier = window.recaptchaVerifier; const result = await firebase .auth() .signInWithPhoneNumber('+' + state.phone, appVerifier); if (result) { setTimeLeft(60); setIsDisabled(false) toast.success('OTP sent to your phone number'); openModalHandler(); setOtpInfo((prev: any) => ({ ...prev, confirmResult: result })); } } catch (error) { console.log(error) toast.error(error.message); setVerifyNumberLoader(false); } finally { if (window.recaptchaVerifier) { window.recaptchaVerifier.reset(); } setVerifyNumberLoader(false); } };
额外优化:组件卸载时清理实例
若注册表单是独立组件,在组件卸载时清理实例避免内存泄漏:
useEffect(() => { return () => { if (window.recaptchaVerifier) { window.recaptchaVerifier.clear(); delete window.recaptchaVerifier; } }; }, []);
以上修改后,无论首次发送OTP还是用户完成注册后不刷新页面重新操作,都不会再出现实例已销毁的错误。你之前用reset()解决"recaptcha client element has been removed"的思路正确,核心就是避免轻易销毁RecaptchaVerifier实例,优先通过重置状态复用。
内容的提问来源于stack exchange,提问作者SHAHID
相关产品推荐
相关产品推荐

