This is an E-commerce website.
<Route path='products/:productId' element={<Product />} />
Here I am using React dynamic route for showing product’s details when clicked on a product.
I have a ShopContext.jsx file which gets all the products from the server and provides to the other components when needed. Here is the part of that code in my ShopContext.jsx file:
const [all_product, setAll_Product] = useState([]);
useEffect(() => {
fetch(`${process.env.REACT_APP_SERVER_API}/allproducts`)
.then((res) => res.json())
.then((data) => setAll_Product(data));
....
}, [])
This one below is my main product page:
const Product = () => {
const {all_product} = useContext(ShopContext);
const {productId} = useParams();
const product = all_product.find((e)=> e.id === Number(productId))
return (
<div>
<ProductDisplay product = {product}/>
<DescriptionBox/>
<RelatedItems/>
</div>
)
}
export default Product;
It passes the ‘product’ to the product display component and the product display component renders that.
But when I refresh the page, the ‘product’ parameter becomes undefined. It says, "product is undefined". Why? And how can I solve this?
Here is the full shop context file:
mport React, { createContext, useEffect, useState } from "react";
export const ShopContext = createContext(null);
const getDefaultCart = () => {
let cart = {};
for(let i = 0; i < 300 + 1; i++) {
cart[i] = 0;
}
return cart;
}
const ShopContextProvider = (props) => {
const [all_product, setAll_Product] = useState([]);
const [cartItems, setCartItems] = useState(getDefaultCart());
useEffect(() => {
fetch(`${process.env.REACT_APP_SERVER_API}/allproducts`)
.then((res) => res.json())
.then((data) => setAll_Product(data));
console.log("context " + all_product);
if(localStorage.getItem('auth-token')) {
fetch(`${process.env.REACT_APP_SERVER_API}/getcart`, {
method: 'POST',
headers: {
Accept: 'application/form-data',
'auth-token': `${localStorage.getItem('auth-token')}`,
'content-type': 'application/json'
},
body: ""
})
.then((res) => res.json())
.then((data) => setCartItems(data));
}
}, [])
const addToCart = (itemId) => {
setCartItems((previous) => ({...previous, [itemId]:previous[itemId] + 1}));
if(localStorage.getItem('auth-token')) {
fetch(`${process.env.REACT_APP_SERVER_API}/addtocart`, {
method: "POST",
headers: {
Accept: "application/form-data",
'auth-token': `${localStorage.getItem('auth-token')}`,
'content-type': "application/json",
},
body: JSON.stringify({"itemId" : itemId})
})
.then((res) => res.json())
.then((data) => console.log(data));
}
}
const removeFromCart = (itemId) => {
setCartItems((previous) => ({...previous, [itemId]:previous[itemId] - 1}));
if(localStorage.getItem('auth-token')) {
fetch(`${process.env.REACT_APP_SERVER_API}/removefromcart`, {
method: "POST",
headers: {
Accept: "application/form-data",
'auth-token': `${localStorage.getItem('auth-token')}`,
'content-type': "application/json",
},
body: JSON.stringify({"itemId" : itemId})
})
.then((res) => res.json())
.then((data) => console.log(data));
}
}
const deleteFromCart = (itemId) => {
setCartItems((previous) => ({...previous, [itemId]:0}));
if(localStorage.getItem('auth-token')) {
fetch(`${process.env.REACT_APP_SERVER_API}/deletefromcart`, {
method: "POST",
headers: {
Accept: "application/form-data",
'auth-token': `${localStorage.getItem('auth-token')}`,
'content-type': "application/json",
},
body: JSON.stringify({"itemId" : itemId})
})
.then((res) => res.json())
.then((data) => console.log(data));
}
}
const getTotalCartAmount = () => {
let totalAmount = 0;
for(const item in cartItems) {
if(cartItems[item] > 0) {
let itemInfo = all_product.find((product) => product.id === Number(item));
totalAmount += itemInfo.new_price * cartItems[item];
}
}
return totalAmount;
}
const getTotalCartItems = () => {
let totalItems = 0;
for(const item in cartItems) {
if(cartItems[item] > 0) {
totalItems += cartItems[item];
}
}
return totalItems;
}
const contextValue = {all_product, cartItems, addToCart, removeFromCart, deleteFromCart, getTotalCartAmount, getTotalCartItems};
return (
<ShopContext.Provider value = {contextValue}>
{props.children}
</ShopContext.Provider>
)
}
export default ShopContextProvider;
2
Answers
I got my answer from ChatGPT. I am giving the answer below. However, while writing this, I have already got two downvotes and yet no one was able to spot the issue. This place is really disappointing. Sorry for wasting your time.
The answer from ChatGPT:
When you refresh the page, the React state is reset, including the state in your
ShopContext
where the product information is stored. TheuseEffect
inShopContext.jsx
fetches the product data only when the component mounts, and since a page refresh causes a remount, the product data is not fetched again, leading to an empty or undefinedall_product
array.To solve this issue, you can consider fetching the product data inside the
Product
component instead of relying solely on the context. You can modify yourProduct
component like this:Thank you so much, man. I was stuck on an error for 2 weeks. But this line from your code was a magic pill.
"<Route path=’products/:productId’ element={} />".
Thank you so much once again..!!! You saved me…!!