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

React Native中Firestore文档校验导致路由跳转异常问题

问题排查:新用户登录后未正确跳转至完善资料页面

场景与问题

业务场景

用户登录后,系统需检查Firestore中是否存在与当前用户UID关联的文档:

  • 若文档存在,跳转至HomeScreen
  • 若文档不存在,跳转至FinishProfileScreen完善资料

原实现代码

/**Library Imports */
import React, { useState, useEffect } from 'react';
import { StyleSheet, Text, View } from 'react-native'
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { StackActions } from '@react-navigation/native';
import firestore from '@react-native-firebase/firestore';
import AsyncStorage from '@react-native-async-storage/async-storage'
import auth from '@react-native-firebase/auth';

/**Screen Imports */
import HomeScreen from '../Screens/HomeScreen';
import FinishProfileScreen from '../Screens/login/FinishProfileScreen'


const Stack = createNativeStackNavigator();

const AppStack = () => {

  
  let curUser = auth().currentUser;  
  let routeName;
  const userRef = firestore().collection('users');
  


  async function docExists(docName, docId) {
    const docRef = firestore().collection(docName).doc(docId);
  
    let docSnapshot = await docRef.get();
    
    if (docSnapshot.exists) {
      console.log("docExists True")
      routeName = "HomeScreen"
      return true;
    } else {
      console.log("docExists False")
      routeName = "FinishProfileScreen"
      return false;
    }

  }

  docExists("users", curUser.uid)

  console.log(routeName)
  
  return (
    <Stack.Navigator initialRouteName={routeName}>
      <Stack.Screen 
          name = "Home"
          component = {HomeScreen}
        />
      <Stack.Screen 
          name = "FinishProfileScreen"
          component = {FinishProfileScreen}
      />
    </Stack.Navigator>
  )
}

export default AppStack

异常现象

创建新用户时,控制台日志显示docExists False,但系统仍跳转到HomeScreen而非FinishProfileScreen,控制台输出如下:

LOG  undefined
 LOG  docExists False
 LOG  undefined
 LOG  docExists False
 LOG  undefined
 LOG  docExists False
 LOG  undefined
 LOG  docExists False
 LOG  undefined
 LOG  docExists False

异常原因分析

  1. 异步操作执行顺序问题:docExists是异步函数,调用时未等待其执行完成就渲染了导航器。组件初始渲染时routeName为undefined,React Navigation会默认选择栈中第一个定义的屏幕(即HomeScreen)。控制台先打印undefined再打印docExists False,也证明了这一点——组件先完成渲染,异步查询后才给routeName赋值,但此时导航器已完成初始化。
  2. 未使用React状态管理:routeName是普通变量,不是React状态。即使异步操作后修改了routeName,也不会触发组件重新渲染,导航器无法感知到路由变化。
  3. initialRouteName仅初始化生效:导航器的initialRouteName仅在第一次创建时生效,后续修改变量值不会改变初始路由设置。

解决方法

通过React状态管理和useEffect钩子调整异步逻辑,确保导航器在查询完成后再初始化,同时添加加载状态提升用户体验。修改后的完整代码如下:

/**Library Imports */
import React, { useState, useEffect } from 'react';
import { StyleSheet, Text, View, ActivityIndicator } from 'react-native'
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import firestore from '@react-native-firebase/firestore';
import auth from '@react-native-firebase/auth';

/**Screen Imports */
import HomeScreen from '../Screens/HomeScreen';
import FinishProfileScreen from '../Screens/login/FinishProfileScreen'


const Stack = createNativeStackNavigator();

const AppStack = () => {
  const [initialRoute, setInitialRoute] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const checkUserDoc = async () => {
      const curUser = auth().currentUser;
      if (!curUser) {
        // 可根据业务需求跳转至登录页
        setLoading(false);
        return;
      }

      const docRef = firestore().collection('users').doc(curUser.uid);
      const docSnapshot = await docRef.get();
      
      if (docSnapshot.exists) {
        console.log("docExists True")
        setInitialRoute("Home");
      } else {
        console.log("docExists False")
        setInitialRoute("FinishProfileScreen");
      }
      setLoading(false);
    };

    checkUserDoc();
  }, []);

  // 查询完成前显示加载状态
  if (loading) {
    return (
      <View style={styles.loadingContainer}>
        <ActivityIndicator size="large" />
      </View>
    );
  }

  // 处理用户未登录的边界情况
  if (!initialRoute) {
    return <Text>请先登录</Text>;
  }

  return (
    <Stack.Navigator initialRouteName={initialRoute}>
      <Stack.Screen 
        name = "Home"
        component = {HomeScreen}
      />
      <Stack.Screen 
        name = "FinishProfileScreen"
        component = {FinishProfileScreen}
      />
    </Stack.Navigator>
  )
}

const styles = StyleSheet.create({
  loadingContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  }
});

export default AppStack

关键改动说明

  • 使用useState定义initialRoute和loading状态,确保状态变化能触发组件重渲染
  • 在useEffect中执行异步查询,确保组件挂载后才进行Firestore操作
  • 添加加载状态,避免查询完成前渲染导航器导致默认路由跳转
  • 检查curUser是否存在,处理用户未登录或auth状态未初始化的边界情况
  • 导航器的initialRouteName使用状态变量,确保查询完成后设置正确的初始路由

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 13:20:33