0

I am following this tutorial to implement a switch navigator for user authentication: https://snack.expo.io/@react-navigation/auth-flow-v3.

However, this.navigation.navigate appears to undefined when I try to navigate to the next screen.

undefined is not an object (evaluating 'this.props.navigation.navigate')

I am using expo for my app, and I've already looked at the solutions posted to a similar question at React Native - navigation issue "undefined is not an object (this.props.navigation.navigate)" to no avail.

import * as React from 'react';
import { createBottomTabNavigator } from 'react-navigation-tabs';

import profile from './app/screens/profile.js'
import home from './app/screens/home.js'
import createCompetition from './app/screens/create.js'
import explore from './app/screens/explore.js'
import Icon from 'react-native-vector-icons/MaterialIcons'
import login from './app/screens/login.js';
import { f } from './config/config.js';
import { ActivityIndicator, AsyncStorage, Button, StatusBar, StyleSheet, View } from 'react-native';
import { createStackNavigator } from 'react-navigation-stack';
import { createAppContainer, createSwitchNavigator } from 'react-navigation';
/** 
 * Tab Stack is the Bottom Navigator for the different pages
*/
const TabStack = createBottomTabNavigator(
  {
    Home: {
      screen: home,
      navigationOptions: {
        tabBarIcon: ({ tintColor }) => (
          <Icon name="home" size={25} style={{ color: tintColor }} />
        ),

      },
    },
    Explore: {
      screen: explore,
      navigationOptions: {
        tabBarIcon: ({ tintColor }) => (
          <Icon name="search" size={25} style={{ color: tintColor }} />
        ),

      }
    },
    Profile: {
      screen: profile,
      navigationOptions: {
        tabBarIcon: ({ tintColor }) => (
          <Icon name="person" size={25} style={{ color: tintColor }} />
        ),

      }
    },
    Create: {
      screen: createCompetition,
      navigationOptions: {
        tabBarIcon: ({ tintColor }) => (
          <Icon name="add" size={25} style={{ color: tintColor }} />
        ),

      }
    },
  },
  {
    tabBarOptions: {
      showIcon: true,
      showLabel: false,
      activeTintColor: 'black',

      style: { backgroundColor: 'white', }
    },

  },
)

/**
 * Loading Screen during authorization process
 */
class AuthLoadingScreen extends React.Component {
  constructor() {
    super();
    this._bootstrapAsync();
  }

  // Fetch the token from storage then navigate to our appropriate place
  _bootstrapAsync = async () => {
    f.auth().onAuthStateChanged(function (user) { //checks if user is signed in or out
      this.props.navigation.navigate(user ? 'App' : 'Auth');
    })
  };

  // Render any loading content that you like here
  render() {
    return (
      <View style={styles.container}>
        <ActivityIndicator />
        <StatusBar barStyle="default" />
      </View>
    );
  }
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
});

const AppStack = createStackNavigator({ Home: TabStack });
const AuthStack = createStackNavigator({ Login: login });
const RootStack = createSwitchNavigator(
  {
    AuthLoading: AuthLoadingScreen,
    App: AppStack,
    Auth: AuthStack,
  },
  {
    initialRouteName: 'AuthLoading',
  }
);

const App = createAppContainer(RootStack);
export default App;

jameszp
  • 37
  • 5

2 Answers2

1

You are not giving access to this to your _bootstrapAsync function and your onAuthStateChanged callback. Just pass the callback inside of it using arrow function, as it autobinds the current function to the current app this

_bootstrapAsync = async () => {
   f.auth().onAuthStateChanged((user) => { //checks if user is signed in or out
   this.props.navigation.navigate(user ? 'App' : 'Auth');
   })
};
Auticcat
  • 4,359
  • 2
  • 13
  • 28
0

The problem is with function keyword, which doesnt bind this keyword. Better replace it with ES6 arrow functions which implictly binds this to the inner scope :

f.auth().onAuthStateChanged((user) => { //checks if user is signed in or out
   this.props.navigation.navigate(user ? 'App' : 'Auth');
   })

Hope it helps .feel free for doubts

Gaurav Roy
  • 11,175
  • 3
  • 24
  • 45