this.props.navigation.navigate не работает в onAuthChanged()

Я новичок в программировании на 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, который представляет собой экран StackNavigator, вызываемый из приложения, js.

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 />;
  }
}

Может ли кто-нибудь сказать мне, где я ошибся, или предложить лучший способ справиться с этим? Спасибо


person jeirman    schedule 22.09.2018    source источник
comment
setState не является мгновенным (это асинхронно), вы уверены, что код входит в любой из операторов if? Вы никогда не должны использовать setState, а затем проверять состояние для значений, поскольку они могут еще не присутствовать.   -  person Ankari    schedule 22.09.2018


Ответы (1)


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 по-прежнему ложно.

Никогда не ожидайте, что setState будет синхронным или мгновенным, все как раз наоборот.

Решение состоит в том, чтобы просто удалить userLoading и сразу же перейти к следующему экрану после определения this.state.user.

person Gianfranco Fertino    schedule 22.09.2018