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>
))};
</>
);
}