When i click on addproduct then it gives error of undefined.. here is my ProductDetails.js code
Why the product setting to localstorage is undefined
import axios from "axios";
import React, { useEffect, useState } from "react";
import { NavLink, useParams } from "react-router-dom";
import { useDispatch } from "react-redux";
import { addToCart } from "../Redux/action/action";
//import { useSelector } from "react-redux";
import { FaStar } from "react-icons/fa";
import Skeleton from "react-loading-skeleton";
const cartItemsFromStorage =
JSON.parse(localStorage.getItem("CartItems")) || [];
const ProductDetails = () => {
const { id } = useParams();
//const cartItems = useSelector((state) => state.handleCart);
const [isLoading, setIsLoading] = useState(false);
const [product, setProduct] = useState(cartItemsFromStorage);
const dispatch = useDispatch();
useEffect(() => {
const fetchProduct = async () => {
try {
setIsLoading(true);
const { data } = await axios.get(
`https://fakestoreapi.com/products/${id}`
);
setProduct(data);
} catch (error) {
console.error("Error fetching product:", error);
} finally {
setIsLoading(false);
}
};
fetchProduct();
}, [id]);
const addProduct = (product) => {
if (product) {
// Update the Redux store
dispatch(addToCart(product));
// Retrieve existing cart items from localStorage
const existingCartItemsJSON = localStorage.getItem("CartItems");
const existingCartItems = existingCartItemsJSON
? JSON.parse(existingCartItemsJSON)
: [];
// Ensure that existingCartItems is an array
if (!Array.isArray(existingCartItems)) {
console.error("Invalid existingCartItems:", existingCartItems);
return;
}
// Add the new product to the existing cart items
const updatedCartItems = [...existingCartItems, product];
// Store the updated cart items back in localStorage
localStorage.setItem("CartItems", JSON.stringify(updatedCartItems));
} else {
console.error("Invalid product:", product);
}
};
const ShowProducts = () => (
<div className="d-flex row" key={product.id}>
<div className="col-md-6 col-sm-3 mt-5">
<img
src={product.image}
alt={product.title}
height="400px"
width="400px"
/>
</div>
<div className="col-md-6 mt-5">
<h4 className="text-uppercase text-black-50">{product.category}</h4>
<h1 className="display-5">{product.title}</h1>
<p className="lead fw-bolder">
Rating {product.rating && product.rating.rate}
<FaStar />
</p>
<h3 className="display-6 fw-bolder my-4">${product.price}</h3>
<p className="lead">{product.description}</p>
<button className="btn btn-primary" onClick={() => addProduct(product)}>
Add to Cart
</button>
<NavLink to="/MyCart" className="btn btn-outline-dark ms-2">
Go to Cart
</NavLink>
</div>
</div>
);
return (
<>
<div className="container py-5">
<div className="row">
{isLoading ? (
<>
{" "}
<div className="col-md-6">
<Skeleton height={400} />
</div>
<div className="col-md-6">
<Skeleton width={300} height={50} />
<Skeleton height={75} />
<Skeleton width={25} height={150} />
<Skeleton height={50} />
<Skeleton height={150} />
<Skeleton height={50} width={100} />
<Skeleton height={50} width={100} />
</div>
</>
) : (
product && <ShowProducts />
)}
</div>
</div>
</>
);
};
export default ProductDetails;
Here is my Reducer.js code Where i defined addToCart() function
import { ADD_TO_CART, REMOVE_FROM_CART } from "../action/action-type";
const cart = []
const handleCart = (state = cart, action) => {
const product = action.payload;
switch (action.type) {
case ADD_TO_CART:
const existingProduct = state.find((item) => item.id === product.id);
if (existingProduct) {
return state.map((item) =>
item.id === product.id ? { ...item, qty: item.qty + 1 } : item
);
} else {
const product = action.payload;
return [
...state,
{
...product,
qty: 1,
},
];
}
case REMOVE_FROM_CART:
const existingProductToRemove = state.find(
(item) => item.id === product.id
);
if (existingProductToRemove.qty === 1) {
return state.filter((item) => item.id !== product.id);
} else {
return state.map(
(item) =>
item.id === product.id ? { ...item, qty: item.qty - 1 } : item,
localStorage.setItem("CartItems", JSON.stringify(state.cart))
);
}
default:
return state;
}
};
export default handleCart;
when i click on addProduct it is giving undefind error i think it is getting undefined items from local storage or the data sets as undefined..
Please can someone provide me solution stucked in it from 2 days.
2
Answers
there are a few things to consider in your code.
In your component ProductDetails.js, the initial state for product is being set to cartItemsFromStorage, which is defined outside the component. This could be causing the undefined error. It seems you intended to initialize product with an empty object {} instead. You should replace this line:
with
The addProduct function expects a parameter product, but it’s being called without any parameter. When you’re calling it in the JSX button’s onClick handler, make sure you’re passing the product object as an argument:
In your Redux reducer (handleCart.js), you have the following line inside the REMOVE_FROM_CART case:
you’re trying to store the updated cart items into localStorage, but you’re using state.cart, which doesn’t exist. It should be:
Hopefully this will fix your error. But Also make your API calling has some data.
The problem is simply because
cartItemsFromStorage
return an array but you set it toproduct
which is an object. So, the {product && ShowProduct()} always renders, then you try to access things likeproduct.title
it will show asundefined
You just need to refactor a bit to make it works:
Look at your code I can tell that you are learning React. I would like to suggest some good practices for caching. In professional works, caching should be manage by cache manager package like
@tanstack/query
or in your case you’re usingredux
, a similar option isredux-query
(or@reduxjs/toolkit/query
if you’re using@reduxjs/toolkit
). But it is totally fine to try the manual methods like you did first to understand how React works with browser APIs.Have a nice day!