Undefined is not an object (evaluating '_this.props')

I am trying to pass my LitItem to my details page but I am getting:
undefined is not an object (evaluating ‘_this.props’)

here is the top part of my ListItem:

<TouchableOpacity
            style={{flex:1}}
            onPress={()=> this.props.navigation.navigate('ReportDetails', item)}
            >. . .

and here is my StackNavigator in my main component:

const Stack = createStackNavigator();

return (
            <NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="ReportDetails" component={ReportDetails} />
</Stack.Navigator>
)
 </NavigationContainer>

Please help?!

please help me out here someone?

Here is my repo

https://github.com/jbiddulph/react-wow

apparently , this.props is undefined?!

Can we see the code?
Log the this.props object to the console and see what you have there, you might not have the navigation as a prop here. I’d try to use the useNavigation hook, you don’t have to prop drill for it.

I have just tried to implement the useNavigation but was unsuccessful.

here is my main navigation component:

import React, {Component} from 'react';
import {View, Text, StyleSheet} from 'react-native';
import WelcomeScreen from './screens/AppSwitchNavigator/WelcomeScreen';
import HomeScreen from './screens/HomeScreen';
import LoginScreen from './screens/LoginScreen';
import ReportDetails from "./screens/AppSwitchNavigator/ReportDetails";
import SettingsScreen from './screens/SettingsScreen';
import CustomDrawerComponent from "./screens/DrawerNavigator/CustomDrawerComponent";
import LoadingScreen from './screens/AppSwitchNavigator/LoadingScreen';
import ReportsReadScreen from "./screens/HomeTabNavigator/ReportsReadScreen";
import ReportsReadingScreen from "./screens/HomeTabNavigator/ReportsReadingScreen";

import {NavigationContainer} from "@react-navigation/native";
import {createStackNavigator} from '@react-navigation/stack';
import {createDrawerNavigator} from "@react-navigation/drawer";
import {createBottomTabNavigator} from "@react-navigation/bottom-tabs";
import colors from "./assets/colors";
import * as firebase from "firebase/app";
import 'firebase/auth';
import {connect} from 'react-redux';
import SplashScreen from "./screens/SplashScreen";
import {ActionSheetProvider} from "@expo/react-native-action-sheet";
import ReportsCountContainer from "./redux/containers/ReportsCountContainer";
import {Ionicons} from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native';

const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
const Tab = createBottomTabNavigator();


class WatchOutWorthing extends Component {

    constructor(props) {
        super(props);

    }

    componentDidMount() {
        this.checkIfLoggedIn()
        console.log(this.props)
    }

    checkIfLoggedIn = () => {

        let unsubscribe
        try{
            unsubscribe = firebase.auth().onAuthStateChanged(user => {
                if(user){
                    //sign in teh user
                    this.props.signIn(user)
                }
                else{
                    this.props.signOut()
                }
                unsubscribe()
            })
        } catch (e) {
            console.log(e)
            this.props.signOut()
        }
    }

    render() {
        if(this.props.auth.isLoading)
        {
            return <SplashScreen/>
        }

        return (
            <NavigationContainer>
                {!this.props.auth.isSignedIn ?(
                <Stack.Navigator
                    screenOptions={
                        {
                            headerStyle: {
                                backgroundColor: colors.bgMain
                            },
                            headerTintColor: "white"
                        }}
                >
                    <Stack.Screen name="WelcomeScreen" options={{headerShown: false}} component={WelcomeScreen} />
                    <Stack.Screen name="LoginScreen" options={{backTitleVisible: false}} component={LoginScreen} />
                    <Stack.Screen name="ReportDetails" component={ReportDetails}  />
                </Stack.Navigator>
                ):(
                    <ActionSheetProvider>
                        <AppDrawerNavigator/>
                    </ActionSheetProvider>
                )}
            </NavigationContainer>
        );
    }
}

const HomeTabNavigator = () => (

    <Tab.Navigator
        tabBarOptions={{
            style: {
                backgroundColor:colors.bgMain
            },
            activeTintColor:colors.logoColor,
            inactiveTintColor:colors.bgTextInput
        }}
        screenOptions={({route}) => ({
            tabBarIcon: ({color, size}) => {
                switch (route.name) {
                    case 'Reports':
                        return <ReportsCountContainer color={color} type="reports"/>
                    case 'ReportsReading':
                        return <ReportsCountContainer color={color} type="reportsReading"/>
                    case 'ReportsRead':
                        return <ReportsCountContainer color={color} type="reportsRead"/>
                }
            }
        })}
    >
        <Tab.Screen options={{tabBarLabel: 'Total'}} name="Reports" component={HomeScreen} />
        <Tab.Screen options={{tabBarLabel: 'New'}} name="ReportsReading" component={ReportsReadingScreen} />
        <Tab.Screen options={{tabBarLabel: 'Saved'}} name="ReportsRead" component={ReportsReadScreen} />
    </Tab.Navigator>
)

const getHeaderTitle = route => {
    const routeName = route.state ? route.state.routes[route.state.index].name
        :'Home'

    switch(routeName){
        case "Reports":
            return "Home"
        case "ReportsReading":
            return "New"
        case "ReportsRead":
            return "Saved"
        default: "Reports"
    }
}

const HomeStackNavigator = ({navigation}) => (

    <Stack.Navigator
        screenOptions={{
            headerStyle: {backgroundColor: colors.bgMain},
            headerTintColor: 'white',
            headerLeft: ()=> (
                <Ionicons onPress={()=>navigation.openDrawer()} name="ios-menu" size={30} color="white"  style={{marginLeft:10}}/>
            )
        }}
    >
        <Stack.Screen
            options={({route}) => ({
              title:getHeaderTitle(route)
            })}
            name="Home"
            component={HomeTabNavigator}
            navigation={navigation}
        />
    </Stack.Navigator>
)

const AppDrawerNavigator = ({navigation}) => (
    <Drawer.Navigator
        drawerContent={props => <CustomDrawerComponent {...props}/>}
    >
        <Drawer.Screen
            options={{drawerIcon:()=><Ionicons name="ios-home" size={24}/>}}
            name="HomeScreen"
            component={HomeStackNavigator}
        />
        <Drawer.Screen
            options={{drawerIcon:()=><Ionicons name="ios-settings" size={24}/>}}
            name="Settings"
            component={SettingsScreen}
        />
    </Drawer.Navigator>
)


const mapStatetoProps = state => {
    return {
        auth: state.auth
    }
}

const mapDispatchToProps = dispatch => {
    return {
        signIn: user => dispatch({type: 'SIGN_IN', payload: user}),
        signOut: () => dispatch({type: 'SIGN_OUT'})
    }
}
export default connect(mapStatetoProps,mapDispatchToProps)(WatchOutWorthing);

const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center'
    }
})

here is my HomeScreen component:

import React from 'react';
import { StyleSheet, Text, View, SafeAreaView, TouchableOpacity, TextInput, FlatList, Alert, Image, ActivityIndicator } from 'react-native';
import ReportCount from '../components/ReportCount';
import { Ionicons, MaterialIcons } from '@expo/vector-icons';
import CustomActionButton from '../components/CustomActionButton';
import colors from '../assets/colors';
import * as firebase from 'firebase/app';
import 'firebase/storage';
import 'firebase/database';
import { snapshotToArray } from '../helpers/firebaseHelpers';
import ListItem from "../components/ListItem";
import AddReportModal from "../components/AddReportModal";
import {connect} from "react-redux";
import {compose} from 'redux';
import {connectActionSheet} from "@expo/react-native-action-sheet";
import store from "../redux/store";
import reports from "../redux/reducers/reportsReducer";
import ListEmptyComponent from "../components/ListEmptyComponent";
import Swipeout from "react-native-swipeout";
import * as ImageHelpers from '../helpers/ImageHelpers';

class HomeScreen extends React.Component {

    constructor(props) {
        super(props)
        this.state = {
            currentUser: {},
            totalCount: 0,
            readingCount: 0,
            readCount: 0,
            textInputData: '',
            reports: [],
            reportsReading: [],
            reportsRead: [],
            reportData: {
                author: ''
            }
        }
    }

    componentDidMount = async () => {

        const user = this.props.currentUser
        const currentUserData = await firebase.database().ref('users').child(user.uid).once('value')
        const reports = await firebase.database().ref('reports').child(user.uid).once('value')
        const reportsArray = snapshotToArray(reports)
        this.setState({
            currentUser: currentUserData.val()
        })
        this.props.loadReports(reportsArray.reverse())
        this.props.toggleIsLoadingReports(false)
    }
    openMenu = () => {
        this.navigation.openDrawer()
    }
    addReport = async report => {
        try {
            // const [modalOpen, setModalOpen] = useState(false)
            // const snapshot = await firebase.database().ref('reports')
            //     .child(this.state.currentUser.uid).orderByChild('name').equalTo(report).once('value')
            // if (snapshot.exists()) {
            //     alert('Unable to add report as already exists')
            // } else {
                this.props.toggleIsLoadingReports(true)
                const key = await firebase.database().ref('reports').child
                    (this.state.currentUser.uid).push().key

                const response = await firebase.database().ref('reports').child(this.state.currentUser.uid).child(key)
                    .set(report)
                report.key = key
                this.props.addReport(report)
            this.props.toggleIsLoadingReports(false)
            //}
        } catch (error) {
            console.log(error)
            this.props.toggleIsLoadingReports(false)
        }
    }
    markAsRead = async (selectReport, index) => {
        try {
            this.props.toggleIsLoadingReports(true)
            await firebase.database().ref('reports').child(this.state.currentUser.uid).child(selectReport.key).update({ saved: true })
            let reports = this.state.reports.map(report => {
                if (report.name == selectReport.name) {
                    return { ...report, saved: true }
                }
                return report
            })
            let reportsReading = this.state.reportsReading.filter(report => report.name !== selectReport.name)
            this.props.markReportAsSaved(selectReport)
            this.props.toggleIsLoadingReports(false)
        } catch (error) {
            console.log(error)
            this.props.toggleIsLoadingReports(false)
        }
    }

    markAsUnread = async(selectReport,index) => {
        try {
            this.props.toggleIsLoadingReports(true)
            await firebase.database().ref('reports').child(this.state.currentUser.uid).child(selectReport.key).update({ saved: false })

            this.props.markReportAsUnsaved(selectReport)
            this.props.toggleIsLoadingReports(false)
        } catch (error) {
            console.log(error)
            this.props.toggleIsLoadingReports(false)
        }
    }

    deleteReport = async(selectReport,index) => {
        try{
            this.props.toggleIsLoadingReports(true)
            await firebase.database().ref('reports').child(this.state.currentUser.uid).child(selectReport.key).remove()
            this.props.deleteReport(selectReport)
            this.props.toggleIsLoadingReports(false)
        }catch (error) {
            console.log(error)
            this.props.toggleIsLoadingReports(false)
        }
    }

    uploadImage = async(image, selectReport) => {
        const ref = firebase.storage().ref('reports').child(this.state.currentUser.uid).child(selectReport.key)
        try {
            // converting to blob
            const blob = await ImageHelpers.prepareBlob(image.uri)
            const snapshot = await ref.put(blob)

            let downloadUrl = await ref.getDownloadURL()
            await firebase.database().ref('reports').child(this.state.currentUser.uid).child(selectReport.key).update({image:downloadUrl})
            blob.close()
            return downloadUrl
        } catch (error) {
            console.log(error)
        }
    }

    openImageLibrary = async(selectReport) => {
        const result = await ImageHelpers.openImageLibrary()
        if(result){
            this.props.toggleIsLoadingReports(true)
            const downloadUrl = await this.uploadImage(result,selectReport)
            this.props.updateReportImage({...selectReport,uri: downloadUrl})
            this.props.toggleIsLoadingReports(false)
        }
    }

    openCamera = async(selectReport) => {
        const result = await ImageHelpers.openCamera()
        if(result){
            this.props.toggleIsLoadingReports(true)
            const downloadUrl = await this.uploadImage(result,selectReport)
            this.props.updateReportImage({...selectReport,uri: downloadUrl})
            this.props.toggleIsLoadingReports(false)
        }
    }

    addReportImage = (selectReport) => {
        const options = ['Select from Photos', 'Camera', 'Cancel']
        const cancelButtonIndex = 2;

        this.props.showActionSheetWithOptions(
            {
                options,
                cancelButtonIndex
            },
            buttonIndex => {
                if (buttonIndex == 0)
                {
                    this.openImageLibrary(selectReport)
                } else if(buttonIndex == 1)
                {
                    this.openCamera(selectReport)
                }

            },
        )
    }

    renderItem = (item, index) => {
        let swipeoutButtons = [
                {
                    text: 'Delete',
                    component: (
                        <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
                            <Ionicons name="ios-trash" size={24} color={colors.txtWhite}/>
                        </View>
                    ),
                    backgroundColor: colors.bgDelete,
                    onPress: () => this.deleteReport(item,index)
                }
            ]
            if(!item.saved)
            {
                swipeoutButtons.unshift({
                    text: 'Save',
                    component: (
                        <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
                            <Text style={{color: colors.txtWhite}}>Save</Text>
                        </View>
                    ),
                    backgroundColor: colors.bgSuccessDark,
                    onPress: () => this.markAsRead(item,index)
                })
            } else {
                swipeoutButtons.unshift({
                    text: 'Unsave',
                    component: (
                        <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
                            <Text style={{color: colors.txtWhite}}>Unsave</Text>
                        </View>
                    ),
                    backgroundColor: colors.bgUnsave,
                    onPress: () => this.markAsUnread(item,index)
                })
            }
            return (
                <Swipeout
                    autoClose={true}
                    style={{marginHorizontal: 5, marginVertical: 5}}
                    backgroundColor={colors.bgMain}
                    right={swipeoutButtons}
                >
                    <ListItem onPress={() => this.addReportImage(item)} editable={true} marginVertical={0} item={item} navigation={this.props.navigation}>
                        {item.saved && (
                            <Ionicons style={{marginRight: 5}} name="ios-heart" color={colors.logoColor} size={30}/>
                        )}
                    </ListItem>
                </Swipeout>
            )
    }
    render() {
        return (
            <View style={styles.container}>
                <SafeAreaView />
                {/*<View style={styles.header}>*/}
                {/*    <MaterialIcons name='menu' size={32} onPress={this.openMenu} style={styles.menu} />*/}
                {/*    <Text style={styles.headerTitle}>Watch Out Worthing</Text>*/}
                {/*    */}
                {/*</View>*/}
                <AddReportModal
                    addReport={this.addReport}
                />
                <View style={styles.container}>
                    {this.props.reports.isLoadingReports && (
                        <View style={{...StyleSheet.absoluteFill,align:'center',justifyContent:'center',zIndex: 1000, elevation: 1000 }}>
                            <ActivityIndicator size="large" color={colors.logoColor}/>
                        </View>
                    )}
                    <FlatList
                        data={this.props.reports.reports}
                        renderItem={({ item }, index) => this.renderItem(item, index)}
                        keyExtractor={(item, index) => index.toString()}
                        ListEmptyComponent={
                            !this.props.reports.isLoadingReports && (
                                <ListEmptyComponent text="There are no reports yet"/>
                            )
                        }
                    />
                </View>
                {/*<View style={styles.footer}>*/}
                {/*    <ReportCount title='Total' icon='ios-archive' count={this.state.reports.length} />*/}
                {/*    <ReportCount title='New' icon='ios-document' count={this.state.reportsReading.length} />*/}
                {/*    <ReportCount title='Saved' icon='ios-heart' count={this.state.reportsRead.length} />*/}
                {/*</View>*/}
                <SafeAreaView />
            </View>
        )
    }
}
const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: colors.bgMain,
    },
    header: {
        height: 90,
        borderBottomWidth: 0.5,
        borderColor: colors.borderColor,
        alignItems: 'center',
        justifyContent: 'space-around',
        flexDirection: 'row'
    },
    headerTitle: {
        fontSize: 24
    },
    textInput: {
        flex: 1,
        backgroundColor: colors.bgTextInput,
        paddingLeft: 10
    },
    checkMarkButton: {
        backgroundColor: colors.bgSuccess
    },
    listItemContainer: {
        minHeight: 100,
        flexDirection: 'row',
        backgroundColor: colors.listItemBg,
        alignItems: 'center',
        marginVertical: 5
    },
    listItemTitle: {
        fontWeight: '100',
        fontSize: 22,
        color: colors.txtWhite,

    },
    imageContainer: {
        height: 70,
        width: 70,
        marginLeft: 10
    },
    image: {
        flex: 1,
        height: null,
        width: null,
        borderRadius: 35
    },
    listItemTitleContainer: {
        flex: 1,
        justifyContent: 'center',
        paddingLeft: 5
    },
    listEmptyComponent: {
        marginTop: 50,
        alignItems: 'center'
    },
    listEmptyComponentTitle: {
        fontWeight: 'bold'
    },
    markAsReadButton: {
        width: 100,
        backgroundColor: colors.bgSuccess
    },
    markAsReadButtonText: {
        fontWeight: 'bold',
        color: 'white'
    },
    footer: {
        height: 80,
        borderTopWidth: 0.5,
        borderColor: colors.borderColor,
        flexDirection: 'row'
    },
    menu: {
        color: colors.logoColor
    }
});

const mapStateToProps = state => {
    return {
        reports: state.reports,
        currentUser: state.auth.currentUser
    }
}

const mapDispatchToProps = dispatch => {
    return {
        loadReports: reports => dispatch({type:'LOAD_REPORTS_FROM_SERVER', payload: reports}),
        addReport: report => dispatch({type:'ADD_REPORT', payload: report}),
        markReportAsSaved: report => dispatch({type:'MARK_REPORT_AS_SAVED', payload: report}),
        markReportAsUnsaved: report => dispatch({type:'MARK_REPORT_AS_UNSAVED', payload: report}),
        toggleIsLoadingReports: bool => dispatch({type:'TOGGLE_IS_LOADING_REPORTS', payload: bool}),
        deleteReport: report => dispatch({type:'DELETE_REPORT', payload: report}),
        updateReportImage: report => dispatch({type:'UPDATE_REPORT_IMAGE', payload: report})
    }
}

const wrapper = compose(
    connect(mapStateToProps,mapDispatchToProps),
    connectActionSheet
)

export default wrapper(HomeScreen)

here is my ListItem component:

import React from 'react';
import {View, Text, StyleSheet, Image, TouchableOpacity} from 'react-native';
import {Ionicons} from '@expo/vector-icons';
import colors from '../assets/colors';
import CustomActionButton from './CustomActionButton';
import NetworkImage from 'react-native-image-progress'
// import * as Progress from 'react-native-progress/Circle';
import {AnimatedCircularProgress} from 'react-native-circular-progress';

const ListItem = ({item, children, marginVertical, editable, onPress, navigate}) => (


        <TouchableOpacity
            style={{flex:1}}
            onPress={()=> this.props.navigation.navigate('ReportDetails', item)}
            >
            <View style={[styles.listItemContainer, {marginVertical}]}>
                <View style={styles.imageContainer}>
                    <TouchableOpacity
                        disabled={!editable}
                        style={{flex:1, zIndex:1000, elevation: 1000}}
                        onPress={()=>onPress(item)}>
                        {item.image ?
                            <NetworkImage source={{uri: item.image}} style={styles.image}
                                          // indicator={Progress.CircularProgress}
                                          indicator={()=> (<AnimatedCircularProgress size={70} width={5} fill={50} tintColor={colors.logoColor} backgroundColor={colors.bgMain} />)}
                                          indicatorProps={{
                                            size:40,
                                              borderWidth:0,
                                              color: colors.logoColor,
                                              unfilledColor: colors.bgMain
                                          }
                                          }
                                          imageStyle={{borderRadius:35}}
                            />
                            :
                            <Image source={require('../assets/icon.png')} style={styles.image}/>
                        }
                    </TouchableOpacity>
                </View>
                <View style={styles.listItemTitleContainer}>
                    <Text style={styles.listItemTitle}>{item.name}</Text>
                </View>
                {children}
            </View>
        </TouchableOpacity>
        )

ListItem.defaultProps = {
    marginVertical: 5,
    editable: false
}
export default ListItem;

const styles = StyleSheet.create({
    listItemContainer: {
        minHeight:100,
        flexDirection: 'row',
        backgroundColor: colors.listItemBg,
        alignItems:'center'
    },
    listItemTitle: {
        fontWeight: '100',
        fontSize: 22,
        color: colors.txtWhite,

    },
    imageContainer: {
        height: 70,
        width: 70,
        marginLeft:10
    },
    image: {
        flex: 1,
        height: null,
        width: null,
        borderRadius: 35
    },
    listItemTitleContainer: {
        flex:1,
        justifyContent: 'center',
        paddingLeft: 5
    },
})

Can anyone help here please?

ListItem is a function component, so shouldn’t it just be props and not this.props. Also, it looks like you are getting navigate passed as a prop so maybe try using that navigate('ReportDetails', item) instead.

Also, you have to realize it’s pretty hard to help with such a large project. I can’t even get passed the login page so that doesn’t help either.

Thanks, I tried this:

I now get: navigate is not a function ‘navigate’ is undefined

Well then maybe you are not passing it as a prop even though it is there in the code as a parameter to the ListItem component.

Did you try logging the props like suggested earlier? Try replacing the destructured parameters with just props and log it out. Just remember it’s not this.props in a function component.

I think I just needed to deconstruct navigation and navigate