Getting undefined is not an object (evaluating '_this.props.navigation')

Viewed 139635

I'm using DrawerNavigator and I have 3 pages: Router page, mainScreen and a photos page.

I maked a header navbar area and I used This <TouchableHighlight onPress={() => this.props.navigation.navigate('DrawerOpen')}> to open Drawer menu in mainScreen and used that for photos page too, menu is ok in mainScreen but when I click <TouchableHighlight onPress={() => this.props.navigation.navigate('DrawerOpen')}> in photos page, I get the error:

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

Photo

How can I fix that?

My photos page:

import React from 'react';
import { Button, ScrollView, View, Text, StyleSheet, TouchableHighlight } from 'react-native';
import { DrawerNavigator } from 'react-navigation';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import Icon from 'react-native-vector-icons/FontAwesome'

const MyNavScreen = ({ navigation }) => (
  <View>
    <View style={styles.containerNavbar}>
      <TouchableHighlight onPress={() => this.props.navigation.navigate('DrawerOpen')}>
        <Icon name="bars" size={30} color="#fff" />
      </TouchableHighlight>
      <Text style={styles.navbarTitle}>Photos</Text>
    </View>

    <ScrollView>
      <View><Text>photo</Text></View>
      <Button onPress={() => navigation.goBack(null)} title="Go back" />
    </ScrollView>
  </View>
);

const MyPhotosHomeScreen = ({ navigation }) => (
  <MyNavScreen navigation={navigation} />
);
MyPhotosHomeScreen.navigationOptions = {
  title: 'Photos',
  drawerIcon: ({ tintColor }) => (
    <MaterialIcons
      name="photo"
      size={24}
      style={{ color: tintColor }}
    />
  ),
};
export default MyPhotosHomeScreen;

mainScreen:

export default class MainScreen extends React.Component {
    static navigationOptions = {
        drawerLabel: 'Home',
        drawerIcon: ({ tintColor }) => (
            <MaterialIcons
                name="home"
                size={24}
                style={{ color: tintColor }}
            />
        )
    };

    render() {
        return (
            <View>
                <View style={styles.containerNavbar}>
                    <TouchableHighlight onPress={() => this.props.navigation.navigate('DrawerOpen')}>
                        <Icon name="bars" size={30} color="#fff" />
                    </TouchableHighlight>
                    <Text style={styles.navbarTitle}>mainScreen</Text>
                </View>

                <View>
                    <View style={styles.containerFooter}>
                        <Text style={styles.footerTitle}>Footer</Text>
                    </View>
                </View>
            </View>

        )
    }
}
16 Answers

If you are using navigation in child component don't forget to send navigation in props to child

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

Access in child component like this

    props.navigation.navigate("ScreenName")

Binding this worked for me

In my case it worked when I bind this to the method that calls the prop it in the constructor.

constructor(props){
    super(props);
    this.showDetails = this.showDetails.bind(this);// you should bind this to the method that call the props
}

showDetails(_id){
    this.props.navigation.navigate('Details');
}

for functional components try useNavigation hook for deep navigation

Or Simply use arrow function

showDetails = (_id) => {
      this.props.navigation.navigate('Details');
}

because while you use expression function it is going to create it's own scope.


Try this:

import { withNavigation } from 'react-navigation';

withNavigation serves the props all over the project/app, you access the navigation props from anywhere.

and

onPress={() => this.props.navigation.navigate('DrawerOpen')} 

Finally,

export default withNavigation(MyPhotosHomeScreen);

check out this https://reactnavigation.org/docs/en/connecting-navigation-prop.html

If you use TouchableOpacity/Height in your child element, pass it this.props.onPress like this:

<TouchableOpacity onPress={this.props.onPress}/>

Then call the onPress function in your parent component like this:

<Parent onPress={this.Handlepress} />

very simple: follow some steps here

  1. import {useNavigation} from '@react-navigation/native';

  2. const Home =()=>{

//add this line under function scope.

const navigation = useNavigation();

return(

<TouchableOpacity onPress={() => navigation.navigate('Detail')}>

//your code.......................

)

}

This is how I have done it in React Navigation 2 release: I call the openDrawer() method from a StackNavigator that is a child navigator of the DrawerNavigator.

This is my DrawerNavigator:

export const Drawer = DrawerNavigator(
    {
        MyAccount: {screen: TabsStack},
    });


export const TabsStack = StackNavigator({

    Tabs: {
        screen: Tabs, navigationOptions: ({navigation}) => ({
            headerLeft: (
                <TouchableOpacity style={{marginLeft: 10, marginTop: 3}}
                                  onPress={() => navigation.openDrawer()}>
                    <Image source={require('./assets/menu_h.png')}/>
                </TouchableOpacity>)
        })

functional components take props as argument. You should try this

const MyNavScreen = ({props}) =>

and then call the props without this key word

onPress = {() => props.navigation.navigate('DrawerOpen')} 

If you want navigation in child component,then you have to get props in child component.

Suppose you have 3 components - Comp_1,Comp_2,Comp_3 and you want to navigate from Comp_2 -> Comp_3. To do this follow these steps.

  1. Pass props in Comp_1 component.Like this

    <Comp_2 navigation={this.props.navigation}/>

  2. Now in Comp_2, we can navigate from Comp_2 -> Comp_3 like this.

    this.props.navigation.navigate('Comp_3');

For example -

<Button onPress = {() => this.props.navigation.navigate('Comp_3')} title = 'Go to Comp_3 Screen' />

In then compnent that you're trying enter to another view you must send the object navigation by you use this in the onPress of component imported

example

Implementing component in a view <CardComponent title="bla bla" navigation={this.props.navigation} />

Component template

<View> <Button title={this.props.title} onPress={()=> this.props.navigation.navigate("anotherAwesomeView")}/> </View>

This problem is because the component that you're trying implement is not defined on stackNavigation, and by this the methot navigation is not avalible for you, and passing this object navigator by params you'll can access to it

i had the same problem when i was using the header component

now you can use the navigation variable in other component like this

<TouchableOpacity onPress={() => { this.props.navigation.navigate("Play");}}>

Happy Codding :)

try this instead you might be missing to import useNavigation() from '@react-navigation/native';

import { useNavigation } from '@react-navigation/native';

function NotificationsScreen() {
const navigation = useNavigation(); 
return(
<Button
        onPress={() => navigation.navigate('Notifications')}
        title="Go to notifications"
      />
);
}

enter code here

For those who are not using class components and prefer functional components: First import useNavigation then from the screen that you wish to navigate from, initiate (declare) the variable navigation = useNavigation();

import { useNavigation } from '@react-navigation/native';

function ScreenToNavigateFrom() {
const navigation = useNavigation(); 
return(
<TouchableOpacity onPress={() => navigation.navigate('AnotherScreen')}>
   <Text style={{fontWeight: "bold", color:"white" }} >Performance</Text>
</TouchableOpacity>
);
}

This answer is courtesy of this gisthub issue: https://github.com/react-navigation/react-navigation/issues/7961

I encountered the same problem. That's how I solved it:

  1. Verify that all your constructors have "props" has argument
  2. Bind the function with use the function this.props.navigation.navigate in the constructor like this: this.your_function = this.your_function.bind(this)

when you defined screen in createStackNavigator , it by default pass a props called navigation, something like this => navigation={this.props.navigation}

but when you using this.props.navigation.navigator("YOUR SCREEN ") and didn't defined this screen at createStackNavigator you must pass the navigation={this.props.navigation} form the screen that you defined in createStackNavigator and then you can use it in your component .

class ProductScreen extends Component {

export default ProductScreen; // make sure bottom this line mention

Call this

  <TouchableOpacity
        onPress = {() => this.props.navigation.navigate('ProductAddScreen')}
        activeOpacity={0.7} style={styles.button}>

       <Text style={styles.message}>{this.state.notFound} </Text>

  </TouchableOpacity>
Related