首页 > 解决方案 > this.props.navigation.navigate 在 onAuthChanged() 中不起作用

问题描述

我是 React Native 编程的新手,并决定通过集成 Firebase 功能来深入研究。我的所有布局都正常工作,但是当我尝试为 Firebase 身份验证编写代码时遇到问题。

问题出在我检查用户是否经过身份验证的一开始(启动画面)(onAuthChanged)。如果已加载用户对象,那么我想在用户对象为空时重定向到登录页面,并在存在有效用户对象时重定向到加载(主)页面。

当满足这些条件但没有任何反应时,想要使用简单的 react-navigation this.props.navigation.navigate 调用。没有重定向,也没有错误。

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

闪屏.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 屏幕

应用程序.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 />;
  }
}

有人可以告诉我哪里出了问题或提出更好的处理方法吗?谢谢

标签: javascriptreact-nativereact-navigationreact-native-firebase

解决方案


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

this.setState 不是瞬时的。在您的情况下, this.setState 在 this 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 仍然是假的。

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

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


推荐阅读