React+Firebase v9实现手机OTP认证时出现verify属性undefined错误
React + Firebase v9 手机OTP认证 "Cannot read properties of undefined (reading 'verify')" 错误解决方案
错误根因
- Firebase v9 模块化
signInWithPhoneNumberAPI参数顺序错误,要求第一个参数传入auth实例,你的代码中将手机号作为第一个参数传入,导致方法内部调用recaptcha实例方法时找不到对应对象 - RecaptchaVerifier初始化时机错误,在表单提交时才初始化实例,实例未完成挂载就触发验证逻辑,导致
verify方法未定义 - 存在死循环风险:Recaptcha验证成功的回调中重复调用提交方法,会反复触发初始化和提交逻辑
- 状态初始化错误:
useState未设置初始空对象,首次读取state.mobile可能返回undefined - Recaptcha容器绑定冲突:将recaptcha容器id绑定在提交按钮上,隐形recaptcha建议使用独立空容器避免事件冲突
修正后代码
import "./styles.css"; import { useState, useEffect } from "react"; import { initializeApp } from "firebase/app"; import { getAuth, RecaptchaVerifier, signInWithPhoneNumber } from "firebase/auth"; const firebaseConfig = { apiKey: "", authDomain: "", projectId: "", storageBucket: "", messagingSenderId: "", appId: "" }; const app = initializeApp(firebaseConfig); const auth = getAuth(app); auth.languageCode = "it"; export default function App() { // 修正状态初始化 const [state, setState] = useState({}); const handelChange = (e) => { const { name, value } = e.target; setState(prev => ({ ...prev, [name]: value })); }; // 组件挂载时初始化recaptcha,避免提交时才初始化 useEffect(() => { window.recaptchaVerifier = new RecaptchaVerifier( "recaptcha-container", { size: "invisible", callback: (response) => { console.log("Recaptcha verified"); // 移除回调中的提交方法调用,避免死循环 }, defaultCountry: "IN" }, auth ); }, []); const onSignInSubmit = async (e) => { e.preventDefault(); const phoneNumber = "+91" + state.mobile; const appVerifier = window.recaptchaVerifier; // 修正signInWithPhoneNumber参数顺序,第一个参数为auth实例 signInWithPhoneNumber(auth, phoneNumber, appVerifier) .then((confirmationResult) => { window.confirmationResult = confirmationResult; console.log("OTP has been sent"); }) .catch((error) => { console.log("sms not send"); console.log(error); // 验证失败时重置recaptcha window.recaptchaVerifier.reset(); }); }; const verifyOtp = (e) => { e.preventDefault(); window.confirmationResult.confirm(state.otp).then((result) => { const user = result.user; console.log("登录成功", user); }).catch((error) => { console.log("OTP验证失败", error); }); }; return ( <div className="App"> <h2>login form </h2> <form onSubmit={onSignInSubmit}> {/* 新增独立recaptcha容器 */} <div id="recaptcha-container"></div> <input type="number" name="mobile" placeholder="Mobile number" required onChange={handelChange} /> <button type="submit"> submit </button> </form> <h2>Enter OTP </h2> <form onSubmit={verifyOtp}> <input type="number" name="otp" placeholder="OTP number" required onChange={handelChange} /> <button type="submit">submit</button> </form> </div> ); }
内容的提问来源于stack exchange,提问作者Ankur
相关产品推荐
相关产品推荐

