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

React Navigation v5中navigation.navigate失效及Firebase鉴权跳转问题

解决React Navigation v5中Loading组件无法调用navigation.navigate的问题

嘿,我之前也踩过这个坑!你遇到的TypeError: undefined is not an object (evaluating '_this.props.navigation.navigate')错误,本质原因是你的LoadingScreen组件没有拿到React Navigation注入的navigation props——因为它不是作为导航栈里的屏幕组件被渲染的,而是直接放在App.js里返回,不在导航容器的上下文范围内,所以props.navigation自然是undefined。

下面给你两种可行的解决方案,推荐第一种,结构更清晰:

方案一:将LoadingScreen加入根导航栈

把LoadingScreen、AuthStack、BottomTabs都统一放到一个根栈里,让React Navigation能给LoadingScreen注入navigation props。

步骤1:修改App.js的导航结构

import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import LoadingScreen from './Loading';
import AuthStack from './AuthStack';
import BottomTabs from './BottomTabs';

const RootStack = createStackNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <RootStack.Navigator 
        initialRouteName="Loading"
        screenOptions={{ headerShown: false }} // 隐藏所有栈的头部
      >
        <RootStack.Screen name="Loading" component={LoadingScreen} />
        <RootStack.Screen name="AuthStack" component={AuthStack} />
        <RootStack.Screen name="BottomTabs" component={BottomTabs} />
      </RootStack.Navigator>
    </NavigationContainer>
  );
}

步骤2:修改Loading.js的auth监听逻辑

现在LoadingScreen已经是根栈的一员,能正常拿到navigation props了,记得用replace代替navigate,避免用户按返回键回到Loading页面,还要取消订阅防止内存泄漏:

import React, { Component } from 'react';
import { View, ActivityIndicator, StyleSheet } from 'react-native';
import firebase from 'firebase';

class LoadingScreen extends Component {
  componentDidMount() {
    // 订阅auth状态变化
    this.authUnsubscribe = firebase.auth().onAuthStateChanged(user => {
      if (user) {
        // 已登录,跳转到底部标签页
        this.props.navigation.replace('BottomTabs');
      } else {
        // 未登录,跳转到登录注册栈
        this.props.navigation.replace('AuthStack');
      }
    });
  }

  componentWillUnmount() {
    // 取消订阅,防止内存泄漏
    this.authUnsubscribe();
  }

  render() {
    return (
      <View style={styles.container}>
        <ActivityIndicator size="large" color="#0000ff" />
      </View>
    );
  }
}

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

export default LoadingScreen;

方案二:用withNavigation高阶组件包裹LoadingScreen

如果你不想调整导航结构,可以用withNavigation把LoadingScreen包裹起来,让它能获取导航上下文:

步骤1:修改Loading.js的导出

import React, { Component } from 'react';
import { View, ActivityIndicator, StyleSheet } from 'react-native';
import firebase from 'firebase';
import { withNavigation } from '@react-navigation/compat'; // 引入高阶组件

class LoadingScreen extends Component {
  // 你的componentDidMount和render逻辑和之前一样
  componentDidMount() {
    firebase.auth().onAuthStateChanged(user => {
      if (user) {
        this.props.navigation.replace('BottomTabs');
      } else {
        this.props.navigation.replace('AuthStack');
      }
    });
  }

  render() {
    return (
      <View style={styles.container}>
        <ActivityIndicator size="large" color="#0000ff" />
      </View>
    );
  }
}

// 用withNavigation包裹组件后导出
export default withNavigation(LoadingScreen);

步骤2:确保App.js的导航容器包裹所有内容

你的App.js需要保证NavigationContainer包裹了AuthStack和BottomTabs,这样withNavigation才能拿到导航上下文:

import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import LoadingScreen from './Loading';

export default function App() {
  return (
    <NavigationContainer>
      <LoadingScreen />
    </NavigationContainer>
  );
}

注意事项

  • 优先用replace而不是navigate:这样跳转后,LoadingScreen会从导航栈中移除,用户按返回键不会回到加载页面
  • 一定要取消auth状态订阅:在componentWillUnmount里调用订阅返回的函数,防止内存泄漏
  • 确认Firebase已正确初始化:如果auth监听没触发,检查Firebase配置是否正确,有没有在App启动时初始化

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:26:18