this.props.navigation.navigate无法在onAuthChanged()

时间:2018-09-22 16:47:22

标签: javascript react-native react-navigation react-native-firebase

我是React Native编程的新手,因此决定通过集成Firebase功能来深入研究。我可以使用所有布局,但是在尝试为Firebase身份验证编码时遇到问题。

问题出在最初(启动屏幕),我在此检查用户是否已通过身份验证( onAuthChanged )。 如果已加载用户对象,那么我想在用户对象为null时重定向到登录页面,在有有效用户对象时重定向到加载(主)页面。

当满足这些条件但什么都没有发生时,想使用一个简单的反应导航this.props.navigation.navigate调用。没有重定向,也没有错误。

很确定这一定是我的基本错误,但我找不到。 所有相关代码都在ComponentDidMount()

SplashScreen.js

import React, { Component } from "react";
import {
  View,
  Text,
  StyleSheet,
  SafeAreaView,
  Image,
  TouchableOpacity
} from "react-native";

import { Transition } from "react-navigation-fluid-transitions";
import firebase from "react-native-firebase";

class SplashScreen extends Component {
  constructor(props) {
    super(props);
    this.unsubscriber = null;
    this.state = {
      userLoading: true,
      user: null
    };
  }

  componentDidMount() {
    firebase.auth().onAuthStateChanged(user => {
      console.log("User object = " + JSON.stringify(user));
      console.log("1 - this.props");
      console.log(this.props);
      this.setState({ userLoading: false, user });
      if (!this.state.userLoading && this.state.user) {
        console.log("Loading screen");
        this.props.navigation.navigate("Loading");
      }
      if (!this.state.userLoading && !this.state.user) {
        console.log("Login screen");
        this.props.navigation.navigate("Login");
      }
    });
  }

  componentWillUnmount() {
    if (this.unsubscriber) {
      //this.unsubscriber();
      firebase.unsubscriber();
    }
  }

  render() {
    return (
      <SafeAreaView
        style={{
          flex: 1,
          backgroundColor: "#587AA0",
          alignItems: "center"
        }}
      >
... more layout of the splash screen
}
}
export default SplashScreen;

console.logs全部打印出正确的值(用户对象并且存在this.props.navigation.navigate)

只是什么也没发生:(没有重定向,没有错误

此代码用于SplashScreen.js,这是从App,js调用的StackNavigator屏幕

App.js

    const LoginStack = FluidNavigator(
  {
    Splash: {
      screen: SplashScreen
    },
    Login: {
      screen: LoginScreen
    },
    Setup: {
      screen: SetupScreen
    },
    Tour: {
      screen: TourScreen
    },
    Loading: {
      screen: LoadingScreen
    },
    Main: {
      screen: MainTab
    }
  },
  {
    initialRouteName: "Splash",
    headerMode: "none"
  }
);

export default class App extends React.Component {
  render() {
    return <LoginStack />;
  }
}

有人可以告诉我我哪里出了问题,或者提出解决这个问题的更好方法?谢谢

1 个答案:

答案 0 :(得分:0)

componentDidMount仅在初始渲染后立即触发一次。

this.setState不是瞬时的。就您而言,this.setState在if块之后完全执行。

if (!this.state.userLoading && this.state.user) {
    console.log("Loading screen");
    this.props.navigation.navigate("Loading");
}
if (!this.state.userLoading && !this.state.user) {
    console.log("Login screen");
    this.props.navigation.navigate("Login");
}

因此,if块将不会执行,因为this.state.userLoading仍然为false。

永远不要期望setState是同步的或瞬时的,相反。

解决方案是删除userLoading,并在确定this.state.user之后立即导航到下一个屏幕。