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

React Native Firebase手机号认证页面导航异常及Firestore错误排查

React Native Firebase手机号认证跳转问题及Firestore内部错误修复

问题描述

  1. 手机号验证码可正常发送,但输入验证完成后,无法按逻辑跳转页面(现有用户跳转至Home,新用户跳转至CreateProfile)
  2. 控制台抛出Firestore内部错误:
LOG 0 ERROR [2024-01-27T12:31:58.103Z] @firebase/firestore: Firestore (10.7.2): INTERNAL UNHANDLED ERROR: TypeError: Cannot read property 'includes' of undefined at isSafari

原代码

const [phoneNumber, setPhoneNumber] = useState("");
const [verificationId, setVerificationId] = useState("");
const [verificationCode, setVerificationCode] = useState("");
const [info, setInfo] = useState("");


const handleVerifyVerificationCode = async () => {
  try {
    const credential = PhoneAuthProvider.credential(
      verificationId,
      verificationCode
    );
    const result = await signInWithCredential(auth, credential);

    if (result.user) {
      const userExists = await checkIfUserExists(result.user);
      if (userExists) {
        navigation.navigate("Home");
      } else {
        navigation.navigate("CreateProfile");
      }
    } else {
      setInfo("Error: User cancelled sign-in process");
    }
  } catch (error) {
    if (error.code === "auth/code-expired") {
      setInfo(
        "Error: The verification code has expired. Please request a new one."
      );
    } else {
      console.log("Error:", error);
      setInfo(`Error : ${error.message}`);
    }
  }
};

const checkIfUserExists = async (user) => {
  try {
    const userRef = doc(db, "users", user.uid);
    const userDoc = await getDoc(userRef);

    if (!userDoc.exists()) {
      const data = {
        uid: user.uid,
        phoneNumber: user.phoneNumber,
      };
      await setDoc(userRef, data);
      navigation.navigate("CreateProfile", { user: data });
    } else {
      navigation.navigate("Home", { user: userDoc.data() });
    }
  } catch (error) {
    console.error("Error checking user existence: ", error);
    setInfo(
      "Error: There was a problem checking the user's existence. Please try again."
    );
    throw error;
  }
}; 

问题分析与修复

1. 页面跳转逻辑混乱

原代码中checkIfUserExists函数内部已经调用了navigation.navigate,但handleVerifyVerificationCode还在等待该函数返回值后再次执行跳转。同时checkIfUserExists没有返回任何值,导致userExists为undefined,后续跳转逻辑完全失效。

修复方案二选一:

方案一:统一跳转逻辑至handleVerifyVerificationCode

修改checkIfUserExists仅返回用户是否存在的布尔值,跳转逻辑集中处理:

const checkIfUserExists = async (user) => {
  try {
    const userRef = doc(db, "users", user.uid);
    const userDoc = await getDoc(userRef);

    if (!userDoc.exists()) {
      const data = {
        uid: user.uid,
        phoneNumber: user.phoneNumber,
      };
      await setDoc(userRef, data);
      return false; // 标记为新用户
    } else {
      return true; // 标记为现有用户
    }
  } catch (error) {
    console.error("Error checking user existence: ", error);
    setInfo(
      "Error: There was a problem checking the user's existence. Please try again."
    );
    throw error;
  }
};

const handleVerifyVerificationCode = async () => {
  try {
    const credential = PhoneAuthProvider.credential(
      verificationId,
      verificationCode
    );
    const result = await signInWithCredential(auth, credential);

    if (result.user) {
      const userExists = await checkIfUserExists(result.user);
      const userRef = doc(db, "users", result.user.uid);
      const userDoc = await getDoc(userRef);
      
      if (userExists) {
        navigation.navigate("Home", { user: userDoc.data() });
      } else {
        navigation.navigate("CreateProfile", { user: userDoc.data() });
      }
    } else {
      setInfo("Error: User cancelled sign-in process");
    }
  } catch (error) {
    if (error.code === "auth/code-expired") {
      setInfo(
        "Error: The verification code has expired. Please request a new one."
      );
    } else {
      console.log("Error:", error);
      setInfo(`Error : ${error.message}`);
    }
  }
};
方案二:移除handleVerifyVerificationCode中的冗余跳转逻辑

直接保留checkIfUserExists内的跳转逻辑,删除handleVerifyVerificationCode中后续的判断:

const handleVerifyVerificationCode = async () => {
  try {
    const credential = PhoneAuthProvider.credential(
      verificationId,
      verificationCode
    );
    const result = await signInWithCredential(auth, credential);

    if (result.user) {
      await checkIfUserExists(result.user); // 直接交由该函数处理跳转
    } else {
      setInfo("Error: User cancelled sign-in process");
    }
  } catch (error) {
    if (error.code === "auth/code-expired") {
      setInfo(
        "Error: The verification code has expired. Please request a new one."
      );
    } else {
      console.log("Error:", error);
      setInfo(`Error : ${error.message}`);
    }
  }
};

// checkIfUserExists函数保持原逻辑不变

2. Firestore isSafari内部错误

该错误是Firebase JS SDK 10.7.x版本在React Native环境下的兼容性问题,SDK的isSafari检测函数依赖浏览器环境的navigator.userAgent,但React Native中该属性未定义。

修复方案二选一:

  • 降级Firebase版本:将Firebase SDK降级至10.6.0版本,该版本不存在此问题
  • 添加Polyfill:在App入口文件(如App.js)中添加navigator.userAgent的模拟:
// 在文件顶部添加
if (typeof navigator === 'undefined' || !navigator.userAgent) {
  global.navigator = {
    ...global.navigator,
    userAgent: 'ReactNative',
  };
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 08:32:36