You don't have access to this class

Keep learning! Join and start boosting your career

Aprovecha el precio especial y haz tu profesi贸n a prueba de IA

Antes: $249

Currency
$209
Suscr铆bete

Termina en:

2 D铆as
5 Hrs
29 Min
12 Seg

Agregando productos al carrito

15/31
Resources

How do you add products to the shopping cart in e-commerce?

In the exciting world of e-commerce application development, one of the most vital features is the shopping cart. A well-designed shopping cart allows users to review and manage the products selected for purchase. In this session, we will learn how to implement this basic functionality of adding products to the cart when the corresponding button is clicked in an e-commerce.

What steps must be followed to create the cart functionality?

  1. Creating the Side Menu:First, a side menu must be set up to manage the shopping cart. This menu facilitates the visualization and administration of the added products.

  2. Adding products to the cart:You start by defining the global state in which the selected products will be stored. It is crucial that this state is kept up to date each time a product is added to the cart:

    const [cartProducts, setCartProducts] = useState([]);
  3. Implement the logic to update the state:Every time the user clicks on the add icon, a function must be executed that updates the cart state:

    const addProductsToCart = (productData) => { setCartProducts((prevCartProducts) => [...prevCartProducts, productData]);};
  4. Integrate the code for the 'onclick' event:In the product component, we add the functionality by making use of an 'onclick' event handler that calls the addProductsToCart function:

    <div onClick={() => addProductsToCart(productData)}> <PlusIcon/></div>

How to handle product images and product data?

It is common for the products API to use random images, which can cause confusion when adding products to the cart. It is important to base the logic on consistent data such as price and name, thus ensuring product identity:

  • Be sure to use price and name to determine product sameness.
  • Don't worry if the images are different each time, as long as the key data remains consistent.

How to optimize the code to ensure good performance?

  • Comments and code organization: Make sure to properly comment the code to maintain clarity and understandability going forward.
  • Use of Spread Operator: Use the spread operator to avoid overwriting the previous state in cartProducts every time new products are added.
  • Event Handling: Consolidate events in the parent component if they start to cross over into child components.

What's next after adding products to cart?

Once this functionality is established, the next step is to create a preview component, or mini cart, so that users have a quick view of the products in their cart from anywhere in the application. This development makes for a smooth and enhanced user experience.

Not only is this implementation essential, but it is a robust foundation for building a functional, user-oriented e-commerce application. Understanding and manipulating these concepts brings you one step closer to mastering modern web development, so keep exploring and improving your skills!

Contributions 21

Questions 1

Sort by:

Want to see more contributions, questions and answers from the community?

Para solucionar el error que ocurre en el arreglo de im谩genes pueden utilizar el operador Optional chaining (?.)

?.

Ejemplo de c贸mo quedar铆a el c贸digo accediendo a la imagen:

<img
	className="w-full h-full rounded-lg"
        src={context.productToShow.images?.[0]}
        alt={context.productToShow.title}
  />

Este operador se utiliza para acceder a propiedades de objetos anidados de forma segura, evitando errores si alguna de las propiedades no est谩 definida o es nula.

Una gran recomendaci贸n, instalen las extensiones de React Developer Tools, React Context DevTool y Redux DevTools para ver toda la informaci贸n de la aplicaci贸n SIN necesidad de hacer console.log.
No est谩 mal hacer console.log, pero creo que puede servir tambi茅n bastante utilizar estas herramientas y nos ahorramos aunque sea un poco de c贸digo 馃槂

no se si mas adelante se realize esto, pero se puede desestructurar data para no tener que poner data.data repetidamente sino solamente data

La razon de que no salga en consola el primer producto que estefany agrega al carrito es por la posicion donde esta ese console.log(), si lo ponemos en el context justo debajo del estado del carrito de compras si nos muestra ambos productos. Es como si el estado no se terminara de actualizar (setCartProducts), hasta que se cierra la funcion addProductsToCart

No s茅 que tan bien est茅, pero yo solucion茅 el problema del objeto de product detail poniendo el condicional &&, as铆 si no existe ese arreglo ni siquiera me carga el componente, por lo que si tengo images[0] no me dar谩 error, ya que lo carga hasta que haya algo

Pueden colocar el siguienet codigo para que la imagen de Product Detail sea igual a la que muestran en la Card:

const [productToShow, setProductToShow] = useState({
    title: "",
    price: "",
    description: "",
    images: [],
  });

Les dejo un Pantallazo:

El Spread Operator corresponde a un operador el cu谩l distribuye los elementos de un arreglo u objeto, para asignarlos a alguna variable/constante/funci贸n.

La API de [Platzi Fake Store API](https://fakeapi.platzi.com/) esta rota a la fecha 8/mayo/2024. Mi aplicacion dejo de cargar toda la informacion y revisando el contenido de la API, claramente alguien estuvo jugando con ella
const Card = (data) => {
	const context = useContext(ShoppingCartContext)

	const showProduct = (productDetail) => {
		context.openProductDetail()
		context.setProductShow(productDetail)
	}

	const addProductToCart = (productData) => {
		context.setCount(context.count + 1)
		context.setCartProducts([...context.cartProducts, productData])
	}

	return (
		<div 
			className="bg-white cursor-pointer w-56 h-60 rounded-lg" 
			onClick={() => showProduct(data.data)}>
			<figure className="relative mb-2 w-full h-4/5">
				<span className="absolute bottom-0 left-0 bg-white/60 rounded-lg text-black text-xs m-2 px-3 py-0.5">{data.data.category.name}</span>
				<img className="w-full h-full object-cover rounded-lg" src={data.data.images[0]} alt={data.data.title} />
				<div className="absolute top-0 right-0 flex justify-center items-center bg-white w-6 h-6 rounded-full m-2 p-1" onClick={() => addProductToCart(data.data)}>
				<PlusIcon className='h-6 w-6 text-black' />
				</div>
			</figure>
			<p className="flex justify-between">
				<span className="text-sm font-light">{data.data.title}</span>
				<span className="text-lg font-medium">${data.data.price}</span>
				</p>
		</div>
	)
}

Opcionalmente se puede enviar una funcion a los setters de los estados, en lugar de el valor directo:

const onIncrementClick = (e) => {
	e.stopPropagation();
	setCartItems((items) => [...items, data]);
	incrementCount();
};

Dicha funcion recibe como argumento el valor actual del estado

mi c贸digo escrito en TS: ![](https://static.platzi.com/media/user_upload/carbon%20%286%29-c7d4af65-3ab5-49ba-8e0b-e943f7efae1d.jpg)![](https://static.platzi.com/media/user_upload/carbon%20%287%29-07b0b06c-9d7a-43f7-8362-82dafebeddab.jpg)
Me pueden ayudar con este error he seguido tal cual el paso a paso de la profe, y em dice que no es una funci贸n. me ayudan por fa ![](https://static.platzi.com/media/user_upload/image-84dde250-d2f0-4148-b508-9d6f41345fc8.jpg)
Para los que vienen teniendo problemas con la API, les recomiendo pasarse a <https://fakestoreapi.com/> que es m谩s estable
Hoy 1/13/2025 han dado de baja casi que todos los elementos de la API D: solo hay un Item ![](https://static.platzi.com/media/user_upload/image-e0ca224c-32ed-4f7f-8cf7-402519434858.jpg)
Para los que no entienden el por qu茅 no se puede ver en la consola el nuevo valor del **estado**, les dejo la explicaci贸n y el link a la documentaci贸n que habla de esto: **Link:** <https://es.react.dev/reference/react/useState#ive-updated-the-state-but-logging-gives-me-the-old-value> **Explicaci贸n:** lo que sucede es que cuando se actualiza un **estado**, se corre un proceso que no modifica el estado *(cartItems en mi caso)* en el controlador de evento que ya se est谩 ejecutando *(addItemToCar en mi caso)*. Si necesitas usar el siguiente estado, puedes guardarlo en una variable *(cart en mi caso)* antes de pasarlo a la funci贸n de actualizaci贸n: ```js const addItemToCar = (product: Product) => { const cart = [...cartItems, product]; console.log('cart: ', cart); setCartItems([...cartItems, product]); console.log('cartItems: ', cartItems); } ```
Para que si agregas el mismo producto mas de una vez no se repita el objeto, sino que se empiece a sumar yo hice esto: ```js const addProductsToCart = (productData) => { setCount(count + 1); const existingProductIndex = shoppingCartProducts.findIndex( (product) => product.id === productData.id ); console.log(existingProductIndex); if (existingProductIndex !== -1) { const updatedShoppingCartProducts = [...shoppingCartProducts]; updatedShoppingCartProducts[existingProductIndex].qty += 1; setShoppingCartProducts(updatedShoppingCartProducts); } else { const productWithQty = { ...productData, qty: 1 }; const shoppingCartProductsCopy = [ ...shoppingCartProducts, productWithQty, ]; setShoppingCartProducts(shoppingCartProductsCopy); } console.log(shoppingCartProducts); }; ```![](https://static.platzi.com/media/user_upload/image-006f3d75-93c3-4f28-b4a3-66bc80726a2c.jpg)![](https://static.platzi.com/media/user_upload/image-f8f13845-2565-45f5-b337-17f56fc171d7.jpg)
![](https://static.platzi.com/media/user_upload/image-88ccad26-47c0-4d9a-9451-aae9ca0eb1b7.jpg) Para visualizar de una mejor manera lo que pasa cuando le damos clic a agregar, podemos instalar la extensi贸n de React en nuestro navegador, en este caso estoy utilizando Firefox y as铆 se ve cuando el estado se actualiza.
Una forma m谩s f谩cil para mi punto de vista de hacerlo, importando tambi茅n los estados en nuestro archivo Card con useContext. ```js <PlusCircleIcon className="absolute text-sm top-1 right-1 flex justify-center items-center bg-white/90 rounded-full w-6 h-6" onClick={() => { setCount(count + 1) setAddCartProducts([...addCartProducts, data.data]) console.log(addCartProducts) }} /> ```
me sale error en la descripcion, aparece es esl estado de isOpen
se vale hacer esto en ShoppingCartProvider: `./src/Context/index.jsx` ```js export const ShoppingCartProvider = ({ children }) => { // Shopping Cart - Count const [ count, setCount ] = useState(0) // Shopping Cart - Products const [ cartProducts, setCartProducts ] = useState([]) const addProductToCart = (productData) => { const _cartProducts = [...cartProducts, productData] setCartProducts(_cartProducts) setCount(_cartProducts.length) } // ... ````./src/Components/Card/index.jsx````js import { useContext } from 'react' import { ShoppingCartContext } from '../../Context' import { PlusCircleIcon } from '@heroicons/react/24/outline' const Card = (data) => { const { addProductToCart, openProductDetail, setProductDetailData } = useContext(ShoppingCartContext) //... return ( // ... <button onClick={ () => addProductToCart(data.data) } className='absolute top-0 right-0 m-2 cursor-pointer' > <PlusCircleIcon className='w-6 h-6' /> </button> // ... } export default Card ```Mi idea es no tener que exportar/importar setCount y poder hacer toda la manipulaci贸n del estado en un solo lugar... qu茅 opinan?

asi va mi codigo

import { useContext } from 'react';
import { ShoppingCartContext } from '../../Context';
import { PlusIcon } from '@heroicons/react/24/solid';

const Card = ({ category: { name }, ...props }) => {
  const {
    count,
    setCount,
    openProductDetail,
    setproducToShow,
    setcarProducts,
    carProducts,
  } = useContext(ShoppingCartContext);

  const showProduct = (productDetail) => {
    openProductDetail();
    setproducToShow(productDetail);
  };

  const addProductsToCart = () => {
    setCount(count + 1);
    setcarProducts([...carProducts, { ...props }]);

    console.log('entra', { ...props });
  };

  return (
    <div
      className='bg-white cursor-pointer w-56 h-60 rounded-lg'
      onClick={() => showProduct({ ...props })}
    >
      <figure className='relative mb-2 w-full h-4/5'>
        <span className='absolute bottom-0 left-0 bg-white/60 rounded-lg text-black text-xs m-2 px-3 py-0.5'>
          {name}
        </span>
        <img
          className='w-full h-full object-cover rounded-lg'
          src={props.images}
          alt={props.title}
        />
        <button
          onClick={addProductsToCart}
          className='absolute top-0 right-0 flex justify-center items-center bg-white w-6 h-6 rounded-full m-2 p-1'
        >
          <PlusIcon></PlusIcon>
        </button>
      </figure>
      <p className='flex justify-between'>
        <span className='text-sm font-light'>{props.title}</span>
        <span className='text-lg font-medium'>${props.price}</span>
      </p>
    </div>
  );
};

export default Card;