Search code examples
javascriptreactjse-commerce

cart data is not showing up on the screen, but only the console


I was creating a react e-commerce website. but after clicking on "add to cart" and then going to the cart page.

problem 1:- the product details are not showing up on the screen(but is there in the console).

problem 2:- even though I'm adding different products in the cart (such as a shirt and a jeans) and it is changing the quantity BUT the data such as PRICE, IMAGE AND PRODUCT NAME REMAINS THE SAME(that is even though i've added 1 shirt and 1 jeans yet it makes the cart array to 2 shirts), in the below-attached image I've added 3 things i.e a shirt, a jeans and shoes yet it only shows me "shoes" and has incremented the quantity of "shoes to 3"

my App.js =

import './App.css';
import ProductsDisplay from './components/ProductsDisplay';
import { BrowserRouter, Route } from 'react-router-dom';
import { Routes } from 'react-router-dom';
import Cart from './cart/Cart';
import { shopData } from './components/ShopData';
import { useState } from 'react';

function App() {

  const [productItems]= shopData;
  const [cartItems, setCartItems]=useState([]);

  const handleAddProduct=(product)=>{
    const prodExists=cartItems.find(item => item.id === product.id);
    if(prodExists){
      setCartItems(cartItems.map(item => item.id === product.id ? {...prodExists , quantity:prodExists.quantity+1}: item))
    }

    else{
      setCartItems([...cartItems , {...product , quantity:1}])
    }

  }

  return (
    <BrowserRouter className="App">
    <Routes>
      <Route path='/' exact  element={ <> <ProductsDisplay productItems={productItems} cartItems={cartItems} handleAddProduct={handleAddProduct} />  </>} className="co" />
      <Route path='/cart'  element={<Cart cartItems={cartItems} handleAddProduct={handleAddProduct}/>} />
    </Routes>
  </BrowserRouter>
  );
}

export default App;

Cart.js which renders the cart page

import React from 'react'

const Cart = ({ cartItems, productItems }) => {


    return (
        <div>

            <div>
                {cartItems.length === 0 && <p>no items added</p>}
            </div>

            <div>
                {cartItems.map(item => {
                    
                    <div key={item.id}>
                        <img src={item.image} />
                        {console.log(item)}
                    </div>
                    
                })}
            </div>

        </div>

    )
}
export default Cart

ProductDisplay.js , the main homepage which shows the products

import React from 'react'
import { shopData } from './ShopData'
import "./Products.css";
import { Link } from 'react-router-dom';
import "./ProductDisplay.css";

const ProductsDisplay = ({productItems, cartItems , handleAddProduct}) => {


    return (
        <div>
            {shopData.map((item) => (
                <div key={item.id}>
                    <div>
                        <img src={item.imageUrl} />
                    </div>

                    <div>
                        <h2>{item.name}</h2>
                    </div>

                    <div>
                        {item.price}
                    </div>

                    <div>
                        <button onClick={() => handleAddProduct(productItems)}>add to cart</button>
                    </div>


                </div>
            ))}


             <Link to="/cart" className='cart-icon'>
            <button>CART</button>
             </Link>
        </div>

    )
}

export default ProductsDisplay

can somebody Please help


Solution

  • It looks like the mistake is here:

    <button onClick={() => handleAddProduct(productItems)}>add to cart</button>
    

    You are adding the productItems shape (an array of all items) to the cart -- no matter what item they click to add to cart.

    Probably you meant to send the item concerned up:

    <button onClick={() => handleAddProduct(item)}>add to cart</button>
    

    That probably fixes it but, really you should only send the ID also:

    <button onClick={() => handleAddProduct(item.id)}>add to cart</button>
    

    And only store the id of the products in the cart and not the whole product. Otherwise you can get out of sync if something changed about the product serverside. I would need more context on the shape of shopData/the api in general to help with that though.

    Basically you keep only IDs of products in cart, along with their quantity. Then when you need to display whats in the cart, you lookup those product id's in the data coming back from api. This ensures you dont have copies of the products lying around in state.

    Additionally ensure Cart actually outputs something as there could be an issue with the image only.

    import React from 'react'
    
    const Cart = ({ cartItems, productItems }) => {
    
    
        return (
            <div>
    
                <div>
                    {cartItems.length === 0 && <p>no items added</p>}
                </div>
    
                <div>
                    {cartItems.map(item => {
                        
                        <div key={item.id}>
                            <img src={item.image} />
                            Item: {JSON.stringify(item)}
                        </div>
                        
                    })}
                </div>
    
            </div>
    
        )
    }
    export default Cart