React Native Firebase手机号认证页面导航异常及Firestore错误排查
React Native Firebase手机号认证跳转问题及Firestore内部错误修复
问题描述
- 手机号验证码可正常发送,但输入验证完成后,无法按逻辑跳转页面(现有用户跳转至Home,新用户跳转至CreateProfile)
- 控制台抛出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
相关产品推荐
相关产品推荐

