React Native Expo Go集成Firebase登录后无法跳转至MainNavigation问题
问题描述
- 基于React Native Expo Go和Firebase Authentication开发登录系统
- 注册流程正常,可跳转至
LoginSurvey页面,但登录后停留在登录界面(Registration组件),无法进入MainNavigation - 已通过
console.log确认MainNavigation代码块可执行,且用户登录状态存在,但跳转逻辑失效
相关代码(index.js)
import MainNavigation from '../Navigation/MainNavigation'; import Registration from './Registration'; import { useContext, useEffect, useState } from 'react'; import { FIREBASE_AUTH, FIREBASE_DB } from '../firebaseConfig'; import * as WebBrowser from 'expo-web-browser'; import { onAuthStateChanged } from 'firebase/auth'; import { Context } from '../Context/Context'; import { doc, getDoc, setDoc } from 'firebase/firestore/lite'; import AsyncStorage from '@react-native-async-storage/async-storage'; import LoaderAnimation from './LoaderAnimation'; import LoginSurvey from './LoginSurvey'; WebBrowser.maybeCompleteAuthSession(); export default function Index() { const { addUserData, state } = useContext(Context); const [loading, setLoading] = useState(true); const [user, setUser] = useState(null); useEffect(() => { checkLoggedIn(); onAuthStateChanged(FIREBASE_AUTH, async (user) => { setLoading(false); if (user) { storeUser(user); setUser(user); } }) }, []); const checkLoggedIn = async () => { const user = await getUser(); if (user) { addUserData(user); setUser(user); } }; const storeUser = async (user) => { try { await AsyncStorage.setItem("@user", JSON.stringify(user)); } catch (error) { console.error("Error storing user data:", error); } }; const getUser = async () => { try { const userString = await AsyncStorage.getItem("@user"); if (userString) { const user = JSON.parse(userString); return user; } else { return null; } } catch (error) { console.error("Error retrieving user data:", error); return null; } }; const TakeSurvey = async () => { const userRef = doc(FIREBASE_DB, 'users', state.userData.email); try { const docSnap = await getDoc(userRef); if (docSnap.exists()) { const userData = docSnap.data(); const SurveyDone = userData['LoginSurveyTaken']; if (!SurveyDone) { return false; } else { return true; } } } catch (error) { console.log(error); } } return ( <> {loading ? <LoaderAnimation height={'100%'} /> : user ? (TakeSurvey() ? ( <> {console.log('it\' s coming till here')} <MainNavigation /> </> ) : <LoginSurvey />) : <Registration />} </> ); };
问题根源
- 异步函数直接用于渲染条件:
TakeSurvey是异步函数,在JSX三元表达式中调用会返回Promise而非布尔值。JavaScript中Promise属于真值,导致判断逻辑完全失效。 - Context数据未同步:
onAuthStateChanged回调中仅设置了组件内的user状态,未同步更新Context中的userData,导致TakeSurvey中state.userData.email为空,无法正确查询Firestore文档。 - 未处理异步结果等待:组件渲染时未等待
TakeSurvey的异步查询完成,直接根据未确定的结果渲染界面,导致显示异常。
解决方案
1. 新增状态管理问卷查询结果
添加surveyTaken状态存储异步查询结果,并在用户状态变化时触发查询:
export default function Index() { const { addUserData, state } = useContext(Context); const [loading, setLoading] = useState(true); const [user, setUser] = useState(null); const [surveyTaken, setSurveyTaken] = useState(null); // 新增状态存储问卷状态 useEffect(() => { checkLoggedIn(); // 订阅Auth状态变化,添加清理函数避免内存泄漏 const unsubscribe = onAuthStateChanged(FIREBASE_AUTH, async (firebaseUser) => { setLoading(false); if (firebaseUser) { await storeUser(firebaseUser); setUser(firebaseUser); addUserData(firebaseUser); // 同步更新Context数据 } else { setUser(null); setSurveyTaken(null); } }); return unsubscribe; }, [addUserData]); // 当用户或Context数据变化时,查询问卷状态 useEffect(() => { const fetchSurveyStatus = async () => { if (!user || !state.userData?.email) return; try { const userRef = doc(FIREBASE_DB, 'users', state.userData.email); const docSnap = await getDoc(userRef); if (docSnap.exists()) { setSurveyTaken(!!docSnap.data().LoginSurveyTaken); // 确保返回布尔值 } else { // 文档不存在时默认未完成问卷 setSurveyTaken(false); } } catch (error) { console.error("查询问卷状态失败:", error); setSurveyTaken(false); } }; fetchSurveyStatus(); }, [user, state.userData]); // 原有函数保持不变 const checkLoggedIn = async () => { const storedUser = await getUser(); if (storedUser) { addUserData(storedUser); setUser(storedUser); } }; const storeUser = async (user) => { try { await AsyncStorage.setItem("@user", JSON.stringify(user)); } catch (error) { console.error("Error storing user data:", error); } }; const getUser = async () => { try { const userString = await AsyncStorage.getItem("@user"); return userString ? JSON.parse(userString) : null; } catch (error) { console.error("Error retrieving user data:", error); return null; } }; return ( <> {loading ? ( <LoaderAnimation height={'100%'} /> ) : user ? ( surveyTaken === null ? ( <LoaderAnimation height={'100%'} /> {/* 等待问卷状态查询完成 */} ) : surveyTaken ? ( <MainNavigation /> ) : ( <LoginSurvey /> ) ) : ( <Registration /> )} </> ); };
2. 关键优化点
- 移除
TakeSurvey函数,将异步查询逻辑移入useEffect,确保结果存储到状态后再渲染。 - 为
onAuthStateChanged添加清理函数,避免组件卸载后仍监听状态变化导致内存泄漏。 - 使用
!!确保问卷状态返回布尔值,避免undefined或null导致的判断错误。 - 处理Firestore文档不存在的边界情况,默认设置为未完成问卷。
内容的提问来源于stack exchange,提问作者Priyanshu kuntal
相关产品推荐
相关产品推荐

