Eugene Goldberg
Eugene Goldberg

Reputation: 15564

How to properly navigate between screen with react-native-navigation?

In my react-native app I have a log-in screen and a home screen. The logic is: of the log-in process (using Firebase) is successful, and we have a "user" object, we want to navigate from the log-in screen to the home screen. When I attempt to implement this, the auth / log-in part works fine, but the "navigation.navigate" part results into this error:

"TypeError: undefined is not an object (evaluating 'navigation.navigate')".

Here is my App.js:

import React, { useEffect, useState } from 'react';

import { Navigation } from 'react-native-navigation';

import LoginScreen from './src/screens/LoginScreen/LoginScreen';


import {
  SafeAreaView,
  StyleSheet,
  ScrollView,
  View,
  Text,
  StatusBar,
  Button
} from 'react-native';

import {
  Header,
  LearnMoreLinks,
  Colors,
  DebugInstructions,
  ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';

const App = (props) => {

  

  return (
    <View style={styles.root}>
    <LoginScreen />
  </View>
  );
};

App.options = {
  topBar: {
    title: {
      text: 'Home',
      color: 'white'
    },
    background: {
      color: '#4d089a' 
    }
  }
}

Navigation.registerComponent('Home', () => App);

Navigation.events().registerAppLaunchedListener(async () => {
  Navigation.setRoot({
    root: {
      stack: {
        children: [
          {
            component: {
              name: 'Home'
            }
          }
        ]
      }
    }
  });
});
const styles = StyleSheet.create({
  root: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: 'whitesmoke'
  }
});

export default App;

Here is my log-in screen, which has this error-inducing part:

navigation.navigate('Home', {user: user})

:

import React, { useState, useEffect } from 'react'
import { Image, Text, TextInput, TouchableOpacity, View } from 'react-native'
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
import styles from './styles';
import { firebase } from '../../firebase/config'
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

export default function LoginScreen({ navigation }) {
    const [email, setEmail] = useState('')
    const [password, setPassword] = useState('')

    const [loading, setLoading] = useState(true)
    const [user, setUser] = useState(null)

    const Stack = createStackNavigator()
  
    useEffect(() => {
      const usersRef = firebase.firestore().collection('users');
      firebase.auth().onAuthStateChanged(user => {
        if (user) {
          usersRef
            .doc(user.uid)
            .get()
            .then((document) => {
              const userData = document.data()
              setLoading(false)
              setUser(userData)
            })
            .catch((error) => {
              setLoading(false)
            });
        } else {
          setLoading(false)
        }
      });
    }, []);

    const onFooterLinkPress = () => {
        navigation.navigate('Registration')
    }

    const onLoginPress = () => {
        firebase
            .auth()
            .signInWithEmailAndPassword(email, password)
            .then((response) => {
                const uid = response.user.uid
                const usersRef = firebase.firestore().collection('users')
                usersRef
                    .doc(uid)
                    .get()
                    .then(firestoreDocument => {
                        if (!firestoreDocument.exists) {
                            alert("User does not exist anymore.")
                            return;
                        }
                        const user = firestoreDocument.data()
                        navigation.navigate('Home', {user: user})
                    })
                    .catch(error => {
                        alert(error)
                    });
            })
            .catch(error => {
                alert(error)
            })
    }

    return (
        <View style={styles.container}>
            <KeyboardAwareScrollView
                style={{ flex: 1, width: '100%' }}
                keyboardShouldPersistTaps="always">
                <Image
                    style={styles.logo}
                    source={require('../../../assets/icon.png')}
                />
                <TextInput
                    style={styles.input}
                    placeholder='E-mail'
                    placeholderTextColor="#aaaaaa"
                    onChangeText={(text) => setEmail(text)}
                    value={email}
                    underlineColorAndroid="transparent"
                    autoCapitalize="none"
                />
                <TextInput
                    style={styles.input}
                    placeholderTextColor="#aaaaaa"
                    secureTextEntry
                    placeholder='Password'
                    onChangeText={(text) => setPassword(text)}
                    value={password}
                    underlineColorAndroid="transparent"
                    autoCapitalize="none"
                />
                <TouchableOpacity
                    style={styles.button}
                    onPress={() => onLoginPress()}>
                    <Text style={styles.buttonTitle}>Log in</Text>
                </TouchableOpacity>
                <View style={styles.footerView}>
                    <Text style={styles.footerText}>Don't have an account? <Text onPress={onFooterLinkPress} style={styles.footerLink}>Sign up</Text></Text>
                </View>
            </KeyboardAwareScrollView>
        </View>
    )
}

What is the proper way of handling navigation in this scenario?

Upvotes: 0

Views: 278

Answers (1)

Wen W
Wen W

Reputation: 2647

according to this link , you are trying to register the App component as the 'Home' screen in your navigation container. I don't think that's what you want.

Navigation.registerComponent('Home', () => App);

You will also need to register your Home screen, otherwise you won't be able to navigate to it. Your App component will automatically get injected with the navigation prop, so you just pass it along to the Login component. try the following:

const App = (props) => {
  return (
    <View style={styles.root}>
    <LoginScreen ...props/>
  </View>
  );
};

App.options = {
  topBar: {
    title: {
      text: 'Home',
      color: 'white'
    },
    background: {
      color: '#4d089a' 
    }
  }
}

Navigation.registerComponent('Login', () => App);
Navigation.registerComponent('Home', () => YourHomeComponent);

Upvotes: 1

Related Questions