I created a Product Card in React, and in the product card, I want the user to be able to press it and navigate to another Product Detail Screen. Now, every time I initialize the useNavigation, it throws me a "Invalid hook call."
import { TouchableOpacity, Image, StyleSheet, Text, View } from 'react-native'
import React from 'react'
import { useNavigation } from '@react-navigation/native';
const ProductCard = ({ item }) => {
const navigation = useNavigation(); // This Line Throws the Error
return (
<TouchableOpacity
onPress={() => {
navigation.navigate('Product_Details', { item });
}}
style={styles.container}
>
<Image
source={{ uri: item.image }}
style={styles.coverImage}
onError={(error) => console.log('Image load error:', error)}
/>
<View style={styles.content}>
<Text style={styles.brand}>{item.brand}</Text>
<Text style={styles.title}>{item.title}</Text>
<Text style={styles.price}>${item.price}</Text>
</View>
</TouchableOpacity>
);
};
export default ProductCard;
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 10,
margin: 5,
borderWidth: 1,
borderColor: "#e8e8e8",
},
coverImage: {
height: 256,
width: "100%",
},
brand: {
fontSize: 16,
color: "#444444",
fontWeight: "700",
},
price: {
fontSize: 18,
color: "#9C9C9C",
fontWeight: "600",
},
content: {
padding: 15,
},
title: {
fontSize: 14,
color: "#444444",
fontWeight: "450"
}
});
I have it entered in my function, I even tried creating a separate function inside my ProductCard
, and outside my ProductCard
and back calling, but I get the same error every time. Any help would be appreciated!
I call ProductCard
in my homepage, see code below
const HomeScreen = () => {
const [products, setProducts] = useState(data.products);
const [selectedCategory, setSelectedCategory] = useState(null);
return (
// Creating a propertly to show which category is selected
<ScrollView
contentContainerStyle={styles.container}>
{/* Product List */}
<FlatList
ListHeaderComponent={
<>
{/* Adding the categories bar to home page */}
<FlatList
style={styles.catStyle}
data={categories}
renderItem={({ item }) => (
<Category
item={item}
selectedCategory={selectedCategory}
setSelectedCategory={setSelectedCategory}
/>
)}
keyExtractor={(item) => item}
horizontal={true}
showsHorizontalScrollIndicator={false}
/>
</>
}
data={products}
renderItem={ProductCard}
numColumns={2}
contentContainerStyle={{
paddingBottom: 25,
}}
/>
</ScrollView>
);
};
It seems the renderItem
prop consumes a function that returns JSX.
renderItem({ item: ItemT, index: number, separators: { highlight: () => void; unhighlight: () => void; updateProps: (select: 'leading' | 'trailing', newProps: any) => void; } }): JSX.Element;
Now while your ProductCard
component is technically a function that consumes an object argument that matches the renderItem
function signature and returns JSX, there are special rules regarding what is a React function and where and how React hooks can be called. React components are passed as JSX to React and React handles calling the function. The renderItem
prop is calling your ProductCard
function directly.
Update the code to be a function that returns ProductCard
JSX. This would be similar to what you did already with the Category
component.
renderItem={(props) => <ProductCard {...props} />}
or
renderItem={({ item }) => <ProductCard item={item} />}