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;