Cómo hacer que el carrito de una pagina de Compras muestre la cantidad de productos y los productos? [closed]

Estoy construyendo un proyecto de carrito de compras. He avanzado bastante,

  • Ya revisé la sintaxis de todos los componentes, y me parecen, están bien.

  • Pruebas a través de la consola para verificar si se está llamando correctamente el dispatch, y si lo está haciendo.

  • El reducer está retornando un nuevo estado correctamente.

  • Se renderizan en el navegador los elementos

Sin embargo, aún no logro que el carrito de compras realicé la acción de mostrar el contenido, los ítems y la suma de los mismos; tal como lo cree en el componente CartPage.jsx, y cuando voy agregando productos solo me muestra que existe un ítem en el icono del carrito.


    import { useContext } from "react"
    import { CartContext } from "../context/CartContext"
    
    
    export const CartPage = () => {
    
      const { shoppingList, increaseItem, decreaseItem, removePurchase } = useContext(CartContext)
      console.log("Shopping list in CartPage:", shoppingList);
      
      const calculateTotal = () => {
        return shoppingList.reduce((total, item) => total + item.price * item.quantity, 0).toFixed(2) 
      }
      
      const handlePrint = () => {
      //  print()
      };
    
      return ( 
        <>
          <table className="table">
            <thead>
              <tr>
                <th scope="col">Name</th>
                <th scope="col">Price</th>
                <th scope="col">Quantity</th>
                <th scope="col">Remove</th>
              </tr>
            </thead>
            <tbody>
              {
                shoppingList.map(item => (
                  <tr key={item.id}>
                    <th>{item.title}</th>
                    <td>{item.price}</td>
                    <td>{item.quantity}</td>
                    <td>
                      <button className="btn btn-outline-primary"
                      onClick={ () => decreaseItem(item.id) }>-</button>
                      <button className="btn btn-primary"> {item.quantity} </button>
                      <button className="btn btn-outline-primary"
                      onClick={ () => increaseItem(item.id) }>+</button>
                    </td>
                    <td>
                      <button
                      type="button"
                      className="btn btn-danger"
                      onClick={()=>removePurchase(item.id)}>
                      Remove
                      </button>
                      </td>
                  </tr>
                ))
              };
    
              <th> <b>TOTAL: </b> </th>
              <td></td>  
              <td></td>  
              <td>${calculateTotal()}</td>  
    
            </tbody>
          </table>
    
          <div className="d-grid gap-2">
            <button 
            className="btn btn-primary"
            onClick={handlePrint}
            disabled={shoppingList>1}
            > Buy </button>
          </div>
    
        </>
      )
    }


    import './App.css';
    import { Route, Routes, Navigate } from 'react-router-dom';
    import { NavBar } from './Components/NavBar';
    import { ShoppingPage } from './Pages/ShoppingPage';
    import { CartPage } from './Pages/CartPage';
    import { ProductsProvider } from './context/ProductsProvider';
    import { CartProvider } from './context/CartProvider';
    
    function AppCart() {
      return (
        <ProductsProvider>
          <CartProvider>
            <NavBar> </NavBar>
            <div className="container">
              <Routes>
                <Route path='/' element={<ShoppingPage></ShoppingPage>}></Route>
                <Route path='/little cart' element={<CartPage></CartPage>}></Route>  
                <Route path='/*' element={<Navigate to='/' />}></Route> 
              </Routes> 
            </div>    
            </CartProvider>  
        </ProductsProvider>
      );
    }
    
    export default AppCart;

  • En la depuración en consola con (“Add Purchase:”, action.pyload, state); refleja objeto en consola, las características solicitadas y la cantidad es un número que aumenta conforme vas adicionando productos.

  • La prueba realizada con console.log “Adding product:” en el shoppingList presenta los datos correctamente

  • El estado shoppingList refleja los cambios en consola y el quantity está actualizando los cambios


    import { CartContext } from "./CartContext";
    import { useReducer } from "react";
    
    const initialState = []
    
    export const CartProvider = ({ children }) => {
        
    const shoppingReducer = (state = initialState, action = {}) => {
        console.log("Reducer action:", action);
        switch (action.type) {
            case '[CART Add Purchase]':
                console.log("Add Purchase Reducer State:", state);
                console.log("Add Purchase:", action.payload, state);
                const existingProduct = state.find(item => item.id === action.payload.id);
                if (existingProduct) {
                    return state.map(item =>
                        item.id === action.payload.id
                            ? {...item, quantity: item.quantity + 1}
                            : item
                     );
                } else {
                    return [...state, {...action.payload, quantity: 1 }];
                }
                           
            case '[CART] Increase item Purchase': // TODO: Add quantity and to modify
                console.log("Increase Reducer State:", state);
                        return state.map(item => 
                            item.id === action.payload 
                            ? {...item, quantity: item.quantity + 1}
                            : item
                        );
                        
            case '[CART] Decrease item Purchase': // TODO: Add quantity and to modify
                        return state.map(item => 
                            item.id === action.payload 
                            ? {...item, quantity: item.quantity - 1 }
                            : item
                        );
    
            case '[CART] Remove Purchase':
                return state.filter(item => item.id !== action.payload)
    
            default:
                return state;
        }
    }; 
    
    
        const [shoppingList, dispatch] = useReducer(shoppingReducer, initialState)
        console.log("Shopping list in CartPage:", shoppingList);
    
        const addPurchase = (product) => {
            console.log("Adding product:", product);
            const action = {
                type: '[CART Add Purchase]',
                payload: product 
            } 
            dispatch(action)    
        }
    
        const increaseItem = (id) => { 
            const action = {
                type: '[CART] Increase item Purchase',
                payload: id
            }              
            dispatch(action)
            console.log("Increasing item with ID:", id); // Depuration
            dispatch({ type: '[CART] Increase item Purchase', payload: id });
    
        };
    
        const decreaseItem = (id) => {
            const action = {
                type: '[CART] Decrease item Purchase',
                payload: id
            }                         
            dispatch(action)    
        };
    
        const removePurchase = (id) => { 
            const action = {
                type: '[CART] Remove Purchase',
                payload: id
            }          
            dispatch(action)    
        };
    
    
      return (
        <CartContext.Provider value={{shoppingList, addPurchase, increaseItem, decreaseItem, removePurchase}} >
            {children}
        </CartContext.Provider>
      )
    } 

Una parte de la Impresión en consola:

    Adding product: {purchase: {…}}purchase: category: "men's clothing"description: "Your perfect pack for everyday use and walks in the forest. Stash your laptop (up to 15 inches) in the padded sleeve, your everyday"id: 1image: "https://fakestoreapi.com/img/81fPKd-2AYL._AC_SL1500_.jpg"price: 109.95rating: {rate: 3.9, count: 120}title: "Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops"[[Prototype]]: Object[[Prototype]]: Object
    CartProvider.jsx:9 Reducer action: {type: '[CART Add Purchase]', payload: {…}}
    CartProvider.jsx:12 Add Purchase Reducer State: [{…}]
    CartProvider.jsx:13 Add Purchase: {purchase: {…}} [{…}]0: purchase: {id: 1, title: 'Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops', price: 109.95, description: 'Your perfect pack for everyday use and walks in th…to 15 inches) in the padded sleeve, your everyday', category: "men's clothing", …}quantity: 5[[Prototype]]: Objectlength: 1[[Prototype]]: Array(0)
    CartProvider.jsx:50 Shopping list in CartPage: [{…}]
    CartProvider.jsx:9 Reducer action: {type: '[CART Add Purchase]', payload: {…}}
    CartProvider.jsx:12 Add Purchase Reducer State: [{…}]
    CartProvider.jsx:13 Add Purchase: {purchase: {…}} [{…}]
    CartProvider.jsx:50 Shopping list in CartPage: [{…}]0: purchase: {id: 1, title: 'Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops', price: 109.95, description: 'Your perfect pack for everyday use and walks in th…to 15 inches) in the padded sleeve, your everyday', category: "men's clothing", …}quantity: 6[[Prototype]]: Objectlength: 1[[Prototype]]: Array(0)
  • Ya revisé el map. en el shoppingList (componente CartPage) y, validé enviando directamente { …product} en el componente CartProvider, pero aún nada.

Esta es la construcción de mi ShoppingPage:


    import React, { useContext } from "react";
    import { Card } from "../Components/Card";
    import { ProductsContext } from "../context/ProductsContext";
    import { CartContext } from "../context/CartContext";
    
    export const ShoppingPage = () => {
      
      const { products } = useContext(ProductsContext);
    
      const handleAdd = ( purchase ) =>{
        addPurchase({
          purchase
        });
      };  
      const handleRemove = (id) =>{
        removePurchase(id)
      };
    
      const {
        addPurchase,
        removePurchase,
      } = useContext(CartContext);
    
      
      return (
        <>
          <h1>Shopping: </h1>
          <hr />
    
          {products.map(product => (
            <Card
              key={product.id}
              image={product.image}
              title={product.title}
              description={product.description}
              price={product.price}
              handleAdd={() => handleAdd(product)}
              handleRemove={() => handleRemove(product.id)}
            >
    
            </Card>
          ))};
        </>
      );
    }