Home > other >  Why am I getting Render Error undefined is not an object (evaluating 'listing.image')?
Why am I getting Render Error undefined is not an object (evaluating 'listing.image')?

Time:02-16

I am relatively new to React Native and I understand that my issue could be a minimal one. I am following along a React Native app building with Mosh Hamedani, and I have reached a point where his code works with him and doesn't seem to do so with me, instead, it's throwing the

Render Error
undefined is not an object (evaluating 'listing.image')

I have read through a good number of questions that are similar and have been solved, but I still can't figure out my situation. I include the components that are believed to be producing this error below:

import React from "react";
import { Image, StyleSheet, View } from "react-native";

import colors from "../config/colors";
import ListItem from "../components/lists/ListItem";
import Text from "../components/Text";

function ListingDetailsScreen({ route }) {
  const listing = route.params;

  return (
    <View>
      <Image source={listing.image} style={styles.image} /> //I don't get what's wrong here.
      <View style={styles.detailsContainer}>
        <Text style={styles.title}>{listing.title}</Text>
        <Text style={styles.price}>ZAR {listing.price}</Text>
        <View style={styles.sellerContainer}>
          <ListItem
            image={require("../assets/products-images/chair.jpg")}
            title="Firm Name"
            subTitle="5 Listings"
          />
        </View>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  detailsContainer: {
    padding: 20,
  },

  image: {
    width: "100%",
    height: 300,
  },

  price: {
    color: colors.secondary,
    fontWeight: "bold",
    fontSize: 20,
    marginVertical: 10,
  },

  sellerContainer: {
    marginVertical: 40,
  },

  title: {
    fontSize: 24,
    fontWeight: "500",
  },
});

export default ListingDetailsScreen;

The component consuming ListingDetails is shown below:

import React from "react";
import { createStackNavigator } from "@react-navigation/stack";
import { TransitionPresets } from "@react-navigation/stack";

import ListingDetailsScreen from "../screens/ListingDetailsScreen";
import ListingsScreen from "../screens/ListingsScreen";

const Stack = createStackNavigator();

const FeedNavigator = () => (
  <Stack.Navigator
    initialRouteName="ListingDetails"
    screenOptions={() => ({
      gestureEnabled: true,
      headerShown: false,
      ...TransitionPresets.ModalPresentationIOS,
    })}
  >
    <Stack.Screen name="Listings" component={ListingsScreen} />
    <Stack.Screen name="ListingDetails" component={ListingDetailsScreen} />
  </Stack.Navigator>
);

export default FeedNavigator;

CodePudding user response:

The object listing is not yet loaded at the time of the return. Try a useEffect() hook and a useState() hook and query in the return area whether the object is already loaded.

Example:

import React, { useEffect, useState } from "react";   // new imports
import { Image, StyleSheet, View } from "react-native";

import colors from "../config/colors";
import ListItem from "../components/lists/ListItem";
import Text from "../components/Text";

function ListingDetailsScreen({ route }) {
  const [listing, setListing] = useState();   // declare the var with useState


useEffect(() => {             // useEffect
  setListing(route.params);
}, [route]);

  return (
    {listing ? (      // conditional operator 
     <View>
        <Image source={listing.image} style={styles.image} /> //I don't get what's wrong here.
        <View style={styles.detailsContainer}>
          <Text style={styles.title}>{listing.title}</Text>
          <Text style={styles.price}>ZAR {listing.price}</Text>
          <View style={styles.sellerContainer}>
            <ListItem
              image={require("../assets/products-images/chair.jpg")}
              title="Firm Name"
              subTitle="5 Listings"
            />
          </View>
        </View>
      </View>
    ) : (
      null  // maybe you can add an spinner or div here to indicate data is loading
    )}   
  );
}

For more information please visit: useState() -> https://reactjs.org/docs/hooks-state.html

useEffect() -> https://reactjs.org/docs/hooks-effect.html

Conditional Rendering -> https://reactjs.org/docs/conditional-rendering.html#inline-if-else-with-conditional-operator

CodePudding user response:

I have figured out the answer to this issue, and it lies in FeedNavigator component. I had set initialRouteName="ListingDetails" which was preventing the default routing.

import React from "react";
import { createStackNavigator } from "@react-navigation/stack";
import { TransitionPresets } from "@react-navigation/stack";

import ListingDetailsScreen from "../screens/ListingDetailsScreen";
import ListingsScreen from "../screens/ListingsScreen";

const Stack = createStackNavigator();

const FeedNavigator = () => (
  <Stack.Navigator
    // initialRouteName="ListingDetails" /* Removed this line and everything worked  as expected */
    screenOptions={() => ({
      gestureEnabled: true,
      headerShown: false,
      ...TransitionPresets.ModalPresentationIOS,
    })}
  >
    <Stack.Screen name="Listings" component={ListingsScreen} />
    <Stack.Screen name="ListingDetails" component={ListingDetailsScreen} />
  </Stack.Navigator>
);

export default FeedNavigator;
  • Related