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

React Native Expo Go集成Firebase登录后无法跳转至MainNavigation问题

问题:React Native Expo + Firebase Auth登录后无法跳转至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 />}
    </>
  );
};

问题根源

  1. 异步函数直接用于渲染条件:TakeSurvey是异步函数,在JSX三元表达式中调用会返回Promise而非布尔值。JavaScript中Promise属于真值,导致判断逻辑完全失效。
  2. Context数据未同步:onAuthStateChanged回调中仅设置了组件内的user状态,未同步更新Context中的userData,导致TakeSurvey中state.userData.email为空,无法正确查询Firestore文档。
  3. 未处理异步结果等待:组件渲染时未等待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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 19:27:35