user3676224
user3676224

Reputation: 873

React Native - navigation issue "undefined is not an object (this.props.navigation.navigate)"

Im following this tutorial https://reactnavigation.org/docs/intro/ and im running into a bit of issues.

Im using the Expo Client app to render my app every time and not a simulator/emulator.

my code is seen down below.

I originally had the "SimpleApp" const defined above "ChatScreen" component but that gave me the following error:

Route 'Chat' should declare a screen. For example: ...etc

so I moved the decleration of SimpleApp to just above "AppRegistry" and that flagged a new error

Element type is invalid: expected string.....You likely forgot to export your component..etc

the tutorial did not add the key words "export default" to any component which I think it may have to do with the fact that im running it on the Expo app? so I added "export default" to "HomeScreen" and the error went away.

The new error that I cant seem to get rid off(based on the code below) is the following:

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

I can't get rid of it unless I remove the "{}" around "const {navigate}" but that will break the navigation when I press on the button from the home screen

import React from 'react';
import {AppRegistry,Text,Button} from 'react-native';
import { StackNavigator } from 'react-navigation';

export default class HomeScreen extends React.Component {
  static navigationOptions = {
    title: 'Welcome',
  };
  render() {
    const { navigate } = this.props.navigation;
    return (
      <View>
        <Text>Hello, Chat App!</Text>
        <Button
          onPress={() => navigate('Chat')}
          title="Chat with Lucy"
        />
      </View>
    );
  }
}



class ChatScreen extends React.Component {
  static navigationOptions = {
    title: 'Chat with Lucy',
  };
  render() {
    return (
      <View>
        <Text>Chat with Lucy</Text>
      </View>
    );
  }
}

const SimpleApp = StackNavigator({
  Home: { screen: HomeScreen },
  Chat: { screen: ChatScreen },
});
AppRegistry.registerComponent('SimpleApp', () => SimpleApp);

Upvotes: 30

Views: 98314

Answers (6)

sandeep talabathula
sandeep talabathula

Reputation: 3308

<ChildComponent navigation={props.navigation} {...data} />

This will make the navigation from the parent propagated to the subsequent child navigations.

Upvotes: 0

ICW
ICW

Reputation: 5760

As Bobur has said in his answer, the navigation prop isn't passed to children of the routed component. To give your components access to navigation you can pass it as a prop to them, BUT there is a better way.

If you don't want to pass the navigation prop all the way down your component hierarchy, you can use useNavigation instead. (Which in my opinion is just cleaner anyways, and reduces the amount of code we have to write):

function MyBackButton() {
  const navigation = useNavigation();

  return (
    <Button
      title="Back"
      onPress={() => {
        navigation.goBack();
      }}
    />
  );
}

https://reactnavigation.org/docs/use-navigation/

This is just really nice because if you have multiple levels of components you wont have to continuously pass the navigation object as props just to use it. Passing navigation just once requires us to 1. Add a prop to the component we want to pass it to. 2. Pass the prop from the parent component. 3. Use the navigation prop to navigate. Sometimes we have to repeat steps 1 and 2 to pass the prop all the way down to the component that needs to use navigation. We can condense steps 1 and 2, no matter how many times they are repeated, into a single useNavigation call with this method.

I think it is best.

Upvotes: 6

Vijay
Vijay

Reputation: 319

Try this Code: onPress={() => this.props.navigation.navigate('Chat')}

Upvotes: 0

Bobur Kobulov
Bobur Kobulov

Reputation: 371

Additional Info: When you are nesting child components, you need to pass navigation as prop in parent component. //parent.js <childcomponent navigation={this.props.navigation}/>

And you can access navigation like this

//child.js

enter image description here this.props.navigation.navigate('yourcomponent');

Reference: https://reactnavigation.org/docs/en/connecting-navigation-prop.html

Upvotes: 37

aofeilin
aofeilin

Reputation: 3

const AppNavigation =()=>{  <SimpleApp  />}

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

Upvotes: -9

Ahmed Khaled Mohamed
Ahmed Khaled Mohamed

Reputation: 396

With Expo you should't do the App registration your self instead you should let Expo do it, keeping in mind that you have to export default component always: Also you need to import View and Button from react-native: please find below the full code:

import React from 'react';
import {
  AppRegistry,
  Text,
  View,
  Button
} from 'react-native';
import { StackNavigator } from 'react-navigation';

 class HomeScreen extends React.Component {
  static navigationOptions = {
    title: 'Welcome',
  };
  render() {
    const { navigate } = this.props.navigation;
    return (
      <View>
        <Text>Hello, Chat App!</Text>
        <Button
          onPress={() => navigate('Chat', { user: 'Lucy' })}
          title="Chat with Lucy"
        />
      </View>
    );
  }
}

 class ChatScreen extends React.Component {
  // Nav options can be defined as a function of the screen's props:
  static navigationOptions = ({ navigation }) => ({
    title: `Chat with ${navigation.state.params.user}`,
  });
  render() {
    // The screen's current route is passed in to `props.navigation.state`:
    const { params } = this.props.navigation.state;
    return (
      <View>
        <Text>Chat with {params.user}</Text>
      </View>
    );
  }
}

const  SimpleAppNavigator = StackNavigator({
  Home: { screen: HomeScreen },
  Chat: { screen: ChatScreen }
});

const AppNavigation = () => (
  <SimpleAppNavigator  />
);

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

Upvotes: 32

Related Questions