How to change screen in react native with react-navigation on click of a button?

craftdeer picture craftdeer · Mar 10, 2018 · Viewed 7.3k times · Source

I have defined all my routes/navigations in my root component (App.js) and am trying to access one of those screens (UserScreen) from a child component(LoginScreen) on click of a button.

Here is my App.js

import React from 'react';
import { StyleSheet, Text, View, TextInput, TouchableHighlight, Button } from 'react-native';
import LoginComponent from './components/LoginComponent';
import { StackNavigator } from 'react-navigation';


class MainWelcome extends React.Component {
 render() {
   return (
    <View>
     <Text>Welcome Page</Text>
    <Button
      title="Login"
      onPress={() => this.props.navigation.navigate('Login')}
    />
  </View>
  );
 }
}

class LoginScreen extends React.Component {
 render() {
  return (
   <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
     <LoginComponent />
   </View>
  );
 }
}

class UserScreen extends React.Component {
 render() {
  return (
  <View>
    <Text>Details Screen</Text>
  </View>
  );
 }
}

 const RootStack = StackNavigator(
  {
  Register: {
   screen: RegisterScreen,
  },
  Login: {
   screen: LoginScreen,
  },
  UserPage: {
   screen: UserScreen,
  },
  Welcome: {
   screen: MainWelcome,
  },
 },
{
  initialRouteName: 'Welcome',
 }
);

export default class App extends React.Component {
  render() {
    return (
     <RootStack />
   );
  }
 }

This is my LoginComponent.js

  import React from 'react';
  import { StyleSheet, Text, View, TouchableHighlight, TextInput, StackNavigator } from 'react-native';

  class LoginComponent extends React.Component {
   constructor(){
    super();
        this.state = {
                loginusername: '',
                loginpassword: '',
                isloggedin: false,
                loggedinuser: null,
        }  
      }

  render() {
   return (
    <View>
      <Text>Please Log In</Text>
    <View>
       <TextInput
           placeholder="USERNAME"
           placeholderTextColor = 'black'
           onChangeText={(loginusername) => this.setState({loginusername})}
            />
      <TextInput
                placeholder="Password"
                placeholderTextColor = 'black'
                onChangeText={(loginpassword) => this.setState({loginpassword})}
            />
      <TouchableHighlight onPress={() => {
        {this.props.navigation.navigate('UserPage')}
        }
      }>
      <View>
      <Text>Login</Text>
      </View>
    </TouchableHighlight>
    </View>  
  </View>
  );
 }
}

export default LoginComponent;

Here in LoginComponent.js, I am doing {this.props.navigation.navigate('UserPage')} to redirect to the userscreen on click of a button but it says TypeError: undefined is not an object (evaluating 'this.props.navigation.navigate'). I am not sure what I am doing wrong and if I should be passing something from the App.js to LoginComponent.js.

Answer

Omar Salah Elboredy picture Omar Salah Elboredy · Mar 11, 2018

If you tried to print your LoginComponent's props you would end up with nothing!, But what if you pass the navigation as prop to your component like this! :

// App.js
class LoginScreen extends React.Component {
...
<LoginComponent navigation={this.props.navigation}/>
...
}

You will end up with functional navigation prop.

Happy user details navigation :)