(React-Native) undefined is not an object (evaluating _'this.props.navigation.navigate')

Viewed 3615

I'm still a novice with react. I want to make my sign In button create a new screen on the press. I've tried multiple attempts but I can't seem to get past this error:

error screen

What is it I'm doing wrong?

LoginForm.js:

    import React, { Component } from 'react';
    import { TextInput, Text, View, StyleSheet, TouchableOpacity } from  'react-native';
    import { StackNavigator } from 'react-navigation';
    import { Button, CardSection, Input, Spinner } from './common';
    import Account from './screens/Account';
    import SignUpForm from './SignUpForm';

    class LoginForm extends Component {
        render() {
            return (
              <View style={styles.container}>
                <TextInput
                  placeholder="Username or email"
                  placeholderTextColor='white'
                  returnKeyType='next'
                  style={styles.input}
                  keyboardType="email-address"
                  onSubmitEditing={() => this.passwordInput.focus()}
                />

                <TextInput
                  secureTextEntry //turns text into *** good for passwords
                  label="Password"
                  placeholder="password"
                  placeholderTextColor='white'
                  secureTextEntry
                  returnKeyType='go'
                  style={styles.input}
                  ref={(input) => this.passwordInput = input}
             />
             <TouchableOpacity style={styles.buttonContainer}>
             <Text style={styles.buttonText}>LOGIN</Text>
             </TouchableOpacity>
             <Text style={styles.textStyle}> Need help logging in?{'\n'}
             or
             </Text>
             <View style={styles.divider} />
             <TouchableOpacity
             style={styles.buttonContainer}
             onPress={() => this.props.navigation.navigate('SignUpForm')}
             >
            <Text style={styles.buttonText}>Sign Up</Text>
            </TouchableOpacity>
            </View>
            );
        }
    }
    export default LoginForm;

**Account.js:**

    import React from 'react';
    import { View, Image, TouchableOpacity, Text, TextInput } from 'react-native';
    import { StackNavigator } from 'react-navigation';
    import { Card, Button, Spinner, CardSection } from '../common';
    import LoginForm from '../LoginForm';


    class Account extends React.Component {
        static navigationOptions = {
            tabBarLabel: 'Account'
        }
        render() {
            return (<View style={styles.containerStyle}>
              <Card>
                <View style={styles.logoContainer}>
                  <Image style={styles.logo} source= . 
            {require('../../Images/ShoeJackCityLogo.png')}/>
                </View>
                <View style={styles.formContainer}>
                  <LoginForm />
                </View>
              </Card>
            </View>);
        }
    }
    export default Account;

**SignUpForm.js:**

    import React, { Component } from 'react';
    import { TextInput, Text, View, StyleSheet, TouchableOpacity } from 'react-native';
    import { Button, CardSection, Input, Spinner } from './common';
    import router from '../../config/router';


    class SignUpForm extends Component {
        render() {
            return (
              <View style={styles.container}>
                <TextInput
                  placeholder="Username or email"
                  placeholderTextColor='white'
                  returnKeyType='next'
                  style={styles.input}
                  keyboardType="email-address"
                  onSubmitEditing={() => this.EmailInput.focus()}
/>
<TextInput
placeholder="Email"
placeholderTextColor='white'
returnKeyType='next'
style={styles.input}
keyboardType="email-address"
onSubmitEditing={() => this.passwordInput.focus()}
/>
<TextInput
secureTextEntry //turns text into *** good for passwords
label="Password"
placeholder="password"
placeholderTextColor='white'
secureTextEntry
returnKeyType='go'
style={styles.input}
ref={(input) => this.passwordInput = input}
/>
<TouchableOpacity style={styles.buttonContainer}>
<Text style={styles.buttonText}>Register</Text>
</TouchableOpacity>
</View>
);
}
}
export default SignUp;
import React from 'react';
import { TabNavigator, StackNavigator } from 'react-navigation';
import { Icon } from 'react-native-elements';

**Router.js**

import Tournaments from '../components/screens/Tournaments';
import Account from '../components/screens/Account';
import Artists from '../components/screens/Artists';
import Shop from '../components/screens/Shop';
import SignUpForm from '../components/SignUpForm';

export const AccountStack = StackNavigator({
  Account: {
    screen: Account,
    navigationOptions: {
    title: 'Account',
    headerBackTitle: null,
  },
  SignUpForm: {
    screen: SignUpForm,
    navigationOptions: {
      title: 'Register'
    }
  },

Ignore this: jsksjkjdkfjkdfkjkdjskfjskjfjksjkjfkjsjfkjskfsjfjsjfksjfjfskfjkskjfjkjskjfjjksfjksfjkfjkfjssfjkfksskjfjsfjk

4 Answers
<LoginForm />

I don't see that you are passing any props into LoginForm which expects this.props.navigation in onPress.

I think you have some confusion related to how the navigation stack works in react-native. So, essentially there are two ways of navigating to a screen.

  1. By declaring it in the StackNavigator class, you are providing the <LoginForm/> component the required navigation object. Once, declared you'll need to navigate to the login form from any screen - like - this.props.navigation.navigate('LoginForm'). Note - you'll be only be able to navigate from either <Account/> or <Signup/> because those two screens currently posses the navigation object in their scope. Now, once you have navigated to the login form component you'll essentially have the navigation object in scope, and your undefined error will go away.

  2. If you decide not to declare the <LoginForm/> screen in the StackNavigator class, you'll need to pass the navigation object explicitly as props to the component, like - <LoginForm navigation={this.props.navigation} />. So, that whenever you render this component, you'll be able to fetch the navigation prop the same way you are using it.

Hope it clears out things for you :)

Your LoginForm component doesn't have 'this.props.navigate' since it is not registered with any navigator, you are calling that component inside your 'Account' component which is registered to navigator. If you want to navigate inside 'LoginForm' you need to pass 'this.props.navigation' like

<LoginForm myNavigation = {this.props.navigation} />

And inside that onPress in LoginForm use

onPress = { ()=> this.props.myNavigation.navigate('SignUpForm) }
Related