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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 11:24:04