No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Convierte tus certificados en títulos universitarios en USA

Antes: $249

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

18 Días
2 Hrs
27 Min
17 Seg

Contador de productos en el carrito

10/31
Recursos

Aportes 50

Preguntas 4

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Podemos usar la desestructuración: permite desempacar valores de arreglos o propiedades de objetos.
En este caso desempacamos los valores que trae ShoppingCartContex para una mejor lectura

const { count, setCount } = useContext(ShoppingCartContex)
 <button
   onClick={() => setCount(count + 1)}
 >
   +
 </button>

Como les dije antes, estamos haciendo click en un botón… usemos la correspondiente etiqueta button, no un div. Hagamos buenas prácticas:

<button
          onClick={() => context.setCount(context.Count + 1)}
          className="absolute top-0 right-0 flex justify-center items-center bg-white w-6 h-6 rounded-full m-2 p-1"
        >
          +
        </button>

En mi navbar estoy haciendo .map a las urls entonces debo verificar si mi url tiene ‘/cart’ para mostrar el contador de los productos:

import { useContext } from "react";
import { NavLink } from "react-router-dom";
import { ShoppingCartContext } from "../../Context";
import { menu1, menu2 } from "../../routes";

export const Navbar = () => {
  const context = useContext(ShoppingCartContext)

  const textDecoration = 'underline underline-offset-4'

  return (
    <nav className="flex items-center justify-between w-full py-5 px-8 text-sm fixed z-10 top-0">
      <ul className='flex gap-3 items-center'>
        {menu1.map(link => (
          <li
            key={link.text}
            className={link.className}
          >
            <NavLink
              to={link.to}
              className={({isActive})=> isActive ? textDecoration : undefined }
            >
              {link.text}
            </NavLink>
          </li>
        ))}
      </ul>
      <ul className='flex gap-3 items-center'>
        {menu2.map(link => (
          <li
            key={link.text}
            className={link.className}
          >
            <NavLink
              to={link.to}
              className={({isActive})=> isActive ? textDecoration : undefined }
            >
              {link.to === '/cart' ? `${link.text} ${context.Count}` : link.text}
            </NavLink>
          </li>
        ))}
      </ul>
    </nav>
  )
}

Les comparto la forma en la que me parece interesante usar el useContext. Sería utilizarlo en el mismo archivo del Context así:

 
Para luego no tener que importar el useContext en cada lugar en el que queramos hacer uso del context. Simplemente llamamos nuestro hook que lo llama internamente. Ejemplo:

mejorar performance del +:
algo que podemos hacer para mejorar la experiencia de usuario es poner una acción en el botón del + para que el usuario sepa que está encima de él, en mi caso le agregué esta linea de código para cambiar el color de fondo cuando el mouse entra en el botón y por supuesto cambiar el Div por un Button, html semantico

hover:bg-blue-500

Otra forma de hacerlo es usando un hook personalizado:

import { useContext } from "react";

import { EcommerceContext } from "../context/EcommerceProvider";

const useEcommerce = () => {
	return useContext(EcommerceContext);
};

export { useEcommerce };

Y así no tienen que crear el useContext en cada componente sino que solamente deben llamar al hook y éste ya contiene todas las variables del provider:

import { useEcommerce } from "../hooks/useEcommerce";

const Card = (data) => {
	const { incrementShoppingCart } = useEcommerce();
	return (
		<div className="bg-gray-200 cursor-pointer w-56 h-60 rounded-lg ">
			<figure className="relative mb-2 w-full h-4/5">
				<span className="absolute bottom-0 left-0 m-2 px-2 bg-white/70 rounded-full text-black text-xs">
					{data?.data?.category}
				</span>
				<img
					className="w-full h-full object-cover rounded-lg"
					src={data?.data?.image}
					alt={data?.data?.title}
				/>
				<button
					className="absolute top-0 right-0 m-2 flex justify-center items-center bg-white w-6 h-6 rounded-full hover:bg-black color-black hover:text-white transition-colors duration-200"
					onClick={incrementShoppingCart}
				>
					+
				</button>
			</figure>
			<p className="flex justify-between px-3">
				<span className="text-sm font-light truncate">{data?.data?.title}</span>
				<span className="text-lg font-bold">${data?.data?.price}</span>
			</p>
		</div>
	);
};

export { Card };

Lo que podemos hacer también es directamente crear la función de aumentar el contador dentro del Context. Además podemos crear una variable “data” con todo lo que vamos a pasarle al value para que quede más limpio el código.

import { createContext, useState } from 'react';
import PropTypes from 'prop-types';

export const Context = createContext();

export const ContextProvider = ({ children }) => {
	ContextProvider.propTypes = {
		children: PropTypes.node.isRequired,
	};

	const [count, setCount] = useState(0);

	const onAdd = () => {
		setCount(count + 1);
	};

	const data = { onAdd, count };

	return <Context.Provider value={data}>{children}</Context.Provider>;
};

Hola comunidad les comparto mis apuntes de la clase, espero les sean de utilidad.
Link aquí:
https://www.notion.so/bg99astro/Contexto-global-8668a3e7a2ce4e398221689616a633e2

Otra forma de hacerlo es con un hook: Context/index.jsx: ```js import { createContext, useState } from "react"; export const ShoppingCartContext = createContext(); export const ShoppingCartProvider = ({ children }) => { const [count, setCount] = useState(0); const incrementCount = () => setCount(count + 1); return ( <ShoppingCartContext.Provider value={{ count, incrementCount }}> {children} </ShoppingCartContext.Provider> ) } ```Hooks/useShoppingCart.jsx: ```js import { useContext } from "react"; import { ShoppingCartContext } from "../Context"; export const useShoppingCart = () => { return useContext(ShoppingCartContext); }; ```Pages/App/index.jsx: ```js import { useRoutes, BrowserRouter } from 'react-router-dom' import { ShoppingCartProvider } from '../../Context'; import Home from '../Home'; import MyAccount from '../MyAccount'; import MyOrder from '../MyOrder'; import MyOrders from '../MyOrders'; import NotFound from '../NotFound'; import SingIn from '../SingIn'; import Navbar from '../../Components/Navbar' import './App.css' import Layout from '../../Components/Layout'; const AppRoutes = () => { let routes = useRoutes([ { path: '/', element: <Home /> }, { path: '/my-account', element: <MyAccount /> }, { path: '/my-order', element: <MyOrder /> }, { path: '/my-orders', element: <MyOrders /> }, { path: '/sing-in', element: <SingIn /> }, { path: '/*', element: <NotFound /> }, ]) return routes; } const App = () => { return ( <ShoppingCartProvider> <BrowserRouter> <Navbar /> <Layout> <AppRoutes /> </Layout> </BrowserRouter> </ShoppingCartProvider> ) } export default App ```Components/Card/index.jsx: ```js import { FaPlus } from "react-icons/fa6"; import { useShoppingCart } from "../../Hooks/useShoppingCart"; const Card = (data) => { const { incrementCount } = useShoppingCart(); return ( <article className='bg-white cursor-pointer w-56 h-60 rounded-lg'>
<figcaption 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 || ''}</figcaption> {data?.data?.title} <FaPlus className='absolute top-0 right-0 flex justify-center items-center bg-white text-black w-6 h-6 rounded-full m-2 p-1' onClick={incrementCount} />

{data?.data?.title} ${data?.data?.title}

</article> ) } export default Card ```Components/Navbar/index.jsx: ```js import { NavLink } from "react-router-dom" import { useShoppingCart } from "../../Hooks/useShoppingCart"; const Navbar = () => { const { count } = useShoppingCart(); const menu1 = [ { to: '/', text: 'Shopi', className: 'font-semibold text-lg' }, { to: '/', text: 'All', className: '' }, { to: '/clothes', text: 'Clothes', className: '' }, { to: '/electronics', text: 'Electronics', className: '' }, { to: '/furnitures', text: 'Furnitures', className: '' }, { to: '/toys', text: 'Toys', className: '' }, { to: '/others', text: 'Others', className: '' } ] const menu2 = [ { to: '/email', text: '[email protected]', className: 'text-black/60' }, { to: '/my-orders', text: 'My Orders', className: '' }, { to: '/my-account', text: 'My Account', className: '' }, { to: '/sing-in', text: 'Sing In', className: '' }, { to: '/shoppcar', text: `🛒 ${count}`, className: '' }, ] return ( <nav className="flex justify-between items-center fixed z-10 top-0 w-full py-5 px-8 text-sm font-light">
    {menu1.map(link => (
  • <NavLink to={link.to} className={({ isActive }) => isActive ? 'underline underline-offset-4' : undefined}> {link.text} </NavLink>
  • ))}
    {menu2.map(link => (
  • <NavLink to={link.to} className={({ isActive }) => isActive ? 'underline underline-offset-4' : undefined}> {link.text} </NavLink>
  • ))}
</nav> ) } export default Navbar ```Con esto ya podemos importar nuestro hook en los componentes que necesitemos y no necesitamos preocuparnos por los detalles de la implementación del context.

una forma de incrementar en contador sin pasar el estado solo es actualizador del estado es de la siguiente manera:

<button
  className="absolute top-0 right-0 flex justify-center items-center bg-white w-6 h-6 rounded-full m-1 p-2"
  value={0}
  onClick={() => {
    setcount((value) => value + 1);
  }}
>
  +
</button>

Card.jsx

const { count } = 
 useContext(ShoppingCartContext)

<li>Carrito{count}</li>

Context.jsx

const [count, setCount] = useState(0)

 const contextValue = {
  count,
  setCount
 }

 return (
  <ShoppingCartContext.Provider 
  value={contextValue}>
   {children}
  </ShoppingCartContext.Provider>
)

en el curso de react router vi que juanDC creava una funcion para recien usarla como constext.AnyThing

Esta es la funcion para llamar ha auth.unaFn || estado

function useAuth() {
  const auth = React.useContext(AuthContext);
  return auth;
}

luego de la importacion ha un componente se llamaba asi:

const auth = useAuth();

para luego usarla asi:

auth.myFuncionExample() 
  • luego de explicar mi logica pregunto de donde sale la variable context?? que alguien me explique porfa…
En el Navbar en vez de estar repitiendo codigo, pueden hacer un array de objetos con los links de la siguiente manera: ```js const navigationLeft = [ { name: 'All', href: '/' }, { name: 'Clothes', href: '/clothes' }, { name: 'Electronics', href: '/electronics' }, { name: 'Furniture', href: '/furniture' }, { name: 'Toys', href: '/toys' }, { name: 'Others', href: '/others' }, ]; const navigationRight = [ { name: 'My Orders', href: '/my-orders' }, { name: 'My Account', href: '/my-account' }, { name: 'Sign In', href: '/sign-in' }, { name: 'My Order', href: '/my-order' }, ]; ```Luego solo tienen que hacer map por cada uno: ```js {navigationLeft.map(item => { return (
  • <NavLink to={item.href} className={({ isActive }) => isActive ? activeStyle : 'flex'} > {item.name} </NavLink>
  • ) })} ```En el caso del lado derecho lo que hice para que muestre el carrito en vez del nombre del link fue esto ```js {navigationRight.map(item => { return (
  • <NavLink to={item.href} className={({ isActive }) => isActive ? activeStyle : 'flex'} > {item.href !== '/my-order' ? item.name : // Si el link es my-order mostrara el carrito <>🛒{count} } </NavLink>
  • ) })} ```El nombre de la tienda y el correo los hice manualmente: ```js
  • <NavLink to="/"> Shopi </NavLink>
  • // ...
  • [email protected]
  • ```
    ![]()![](https://static.platzi.com/media/user_upload/plat1-e6f93287-b097-4c30-b221-275cb9997c50.jpg)Gente yo cree una funcion y luego la llame en el onclick para que se vea mas limpio el onclick
    Para el evento del card al agregar un nuevo item al carrito (+) podemos hacer uso del estado previo del state. \
    setCount(prev => prev + 1)} \> \+ \
    ```jsx
    setCount(prev => prev + 1)} > +
    ```
    Yo aparte de agregar el contador, agregue un estado nuevo para cambiar el icono de cada card para saber si ya fue agragado y si se le vuelve a dar click lo saca del carrito. \---js const { count, setCount } = useContext(ShoppingCardContext);    const \[addCart, setAddCart] = useState(false);   const addCartItem = () => {    if (!addCart) {      setCount(count + 1)      setAddCart(!addCart)    } else {      setCount(count - 1)      setAddCart(!addCart)    }  } \---

    Asi vamos!!!

    Yo decidí limpiar un poco el archivo de Navbar llevandome toda la info donde se listan en objetos cada uno de los items del Navbar, este sería el resultado:

    import { NavLink } from "react-router-dom";
    import { useContext } from "react";
    import { ShoppingCartContext } from "../../Context";
    import { navData } from "../../Assets/nav-data";
    
    const Navbar = () => {
        const context = useContext(ShoppingCartContext);
        const navItems = navData(context);
        const activeStyle = "underline underline-offset-4";
    
        return (
            <nav className="flex justify-between items-center fixed top-0 z-10 w-full py-5 px-8 text-sm font-light">
                <ul className="flex items-center gap-3">
                    {navItems.mainNav.map((link) => (
                        <li className={link.className} key={link.text}>
                            <NavLink 
                                to={link.to}
                                className={({isActive}) => isActive ? activeStyle : undefined}
                            >
                                {link.text}
                            </NavLink>
                        </li>
                    ))}          
                </ul>
                <ul className="flex items-center gap-3">
                    {navItems.asideMenu.map((link) => (
                        <li className={link.className} key={link.text}>
                            <NavLink 
                                to={link.to}
                                className={({isActive}) => isActive ? activeStyle : undefined}
                            >
                                {link.text}
                            </NavLink>
                        </li>
                    ))}
                </ul>
            </nav>
        );
    }
    
    export default Navbar;
    

    Y el archivo donde guardo toda la info de los items del Navbar es este:

    
    function navData(prop) {
    
        const mainNav = [
            {
                to: '/',
                text: 'Shopi',
                className: 'font-semibold text-lg'
            },
            {
                to: '/',
                text: 'All',
                className: ''
            },
            {
                to: '/clothes',
                text: 'clothes',
                className: '' 
            },
            {
                to: '/electronics',
                text: 'electronics',
                className: ''
            },
            {
                to: '/furnitures',
                text: 'furnitures',
                className: ''
            },
            {
                to: '/toys',
                text: 'toys',
                className: ''
            },
            {
                to: '/others',
                text: 'others',
                className: ''
            },
        ];
        
        const asideMenu = [
            {
                to: '/email',
                text: '[email protected]',
                className: 'text-black/60'
            },
            {
                to: '/my-orders',
                text: 'My Orders',
                className: ''
            },
            {
                to: '/my-account',
                text: 'My Account',
                className: ''
            },
            {
                to: '/signin',
                text: 'Sign In',
                className: ''
            },
            {
                to: '/shoppcar',
                text: `🛒 ${prop.counter}`,
                className: ''
            },
        ];
    
      return {
        mainNav,
        asideMenu
      }
    }
    
    export {navData};
    
    

    La carpeta donde hice esto la llamé Assets/nav-data.jsx, no se porque elegí esos nombres pero fue lo primero que se me ocurrio para nombrar estos archivos…

    Me gustaría leer sus comentarios para que me ayuden a darle una mejor estructura de carpetas y de nombres para la solución que hice.

    ✨ ![](

    Asi vamos profe, el carrito funcional ![](https://static.platzi.com/media/user_upload/image-0c0476ec-251c-4bc7-b2fc-7e2376373c12.jpg)
    Este artículo está genial para entender mejor el manejo del contexto con useContext y con Redux

    Estoy haciendo de nuevo este proyecto con TypeScript y me ha costado un montón pero aca les dejo mi código y mi repositorio

    archivo context .tsx

    import React, { createContext, ReactNode, useState, Dispatch, SetStateAction } from "react";
    
    type Props = {
        children: ReactNode,
    };
    
    type ShoppingCartContextType = {
        count: number,
        setCount: Dispatch<SetStateAction<number>>,
    };
    
    export const ShoppingCartContext = createContext<ShoppingCartContextType | null>(null);
    
    export const ShoppingCartProvider: React.FC<Props> = ({ children }: Props) => {
        const [count, setCount] = useState<number>(0);
        console.log('Count:', count)
    
        return (
            <ShoppingCartContext.Provider value={{ count, setCount }}>
                {children}
            </ShoppingCartContext.Provider>
        );
    };
    
    export default ShoppingCartProvider;
    

    archivo card

    import { useContext } from 'react'
    import { Product } from '../../Models/Products'
    import { ShoppingCartContext } from '../../Context'
    
    function Card(data: Product) {
        const context = useContext(ShoppingCartContext)!;
    
        const incrementCount = () => {
            context.setCount(prevCount => prevCount + 1);
        };
    
        return (
    	//Codigo de card
    	<button onClick={incrementCount}> </button>
    )
    
    ![](https://static.platzi.com/media/user_upload/image-8e7cf26a-944a-47b5-8a9e-1f27fa8809d0.jpg)
    ![](https://static.platzi.com/media/user_upload/image-46b4c4d7-069e-4415-975b-b488a9c552c9.jpg)
    Se dañaron las rutas delas images, tienen un formato raro las urls.No se muestran
    hola. tengo el siguiente error al dar click al boton del + Uncaught TypeError: context is undefined onClick index.jsx:14 React 23 \<anonymous> main.jsx:6 favor alguien explicar como se soluciona saludos
    Mi proyecto va de la siguiente manera, lo he cambiado un poco ciertas cositas agrege iconos propiamente en lugar de poner un (+). ![](https://static.platzi.com/media/user_upload/Captura%20desde%202024-02-13%2016-33-23-17069c8e-5920-4d14-9627-c34f5de57108.jpg)
    ![](https://static.platzi.com/media/user_upload/image-87d154cb-d299-473a-b00e-e45f4e942a3a.jpg) tres horas para que se me cambien todos los contadores , jajjaja ahorita a modificarlo ![](https://static.platzi.com/media/user_upload/image-0d9bc9a5-8beb-4dfa-962f-fa3e0d0a4100.jpg)

    va quedando

    Algo que tambien se puede aplicar es que el estado global sea un arreglo que almacene todos los productos y que cada boton agregué un elemento al arreglo. Al final el carrito va a reflejar la longitud de ese arreglo. Con esto podemos reflejar los productos que se agregaron al carrito. `export ``const`` AppContextProvider = ({``children``}) => {  ``const`` [ productsInCart, setProductsInCart ] = useState([]);` `  ``const`` addCartProduct = (``product``) => {    ``const`` products = [...productsInCart];    products.push(product);    console.log(products)    setProductsInCart(products);  }` `  return (    <AppContext.Provider      ``value``={{        addCartProduct,        productsInCart      }}    >      {children}    </AppContext.Provider>  );}`

    Envés de un contador se le pueden pasar los datos del producto que fue agregado al carrito y hacer el contador con .length (una propiedad que retorna el número de elementos de un Array) de esta manera ya incluso se podrían mostrar los productos en el carrito

    // Contexto
    import { createContext, useState } from "react";
    export const CartContext = createContext()
    export const CartProvider = ({ children }) => {
        const [cart, setCart] = useState([])
        const addToCart = (product) => {
            setCart(prevState => ([
                ...prevState,
                {
                    ...product
                }
            ]
            ))
        }
       
        return (
            <CartContext.Provider value={{
                cart,
                addToCart
            }} >
                {children}
            </CartContext.Provider >)
    }
    
    // Añadir producto al carrito. componente Card 
    
    import { CartContext } from "../../Context/Cart"
    import { useContext } from "react";
    
    export function Card({ price, title, category, image, id }) {
        const { addToCart, cart } = useContext(CartContext);
        const checkProductInCart = (product) => {
            return cart.some(item => item.id === product.id)
        }
        const isProductInCart = checkProductInCart({ id })
        return (
            <article className='cursor-pointer w-56 h-60 rounded-lg p-4'>
                <figure className='relative mb-2 w-full h-4/5'>
                    <figcaption className='absolute bottom-0 left-0 bg-white/60 rounded-lg text-black text-xs m-2 px-3 py-0.5'>
                        {category}
                    </figcaption>
                    <img className='w-full h-full object-cover rounded-lg' src={image} alt={title} />
                    <button className='absolute top-0 right-0 flex justify-center items-center bg-white w-6 h-6 rounded-full m-2 p-1 text-black'
                        onClick={() => addToCart({ price, title, category, image, id })}  >
                        {isProductInCart ? 'x' : '+'}
                    </button>
                </figure><p className='flex justify-between'>
                    <span className='text-sm font-light'>{title}</span>
                    <span className='text-lg font-medium'>{price}</span></p>
            </article>
        )
    }
    
    Mostrar Cantidad de productos en el NavBar
    
    import { NavLink } from 'react-router-dom'
    import { categories } from '../../Services/products'
    import { useContext } from 'react';
    import { CartContext } from '../../Context/Cart';
    export const Navbar = () => {
        const { cart } = useContext(CartContext);
    
        return (
            <nav className='flex justify-between items-center bg-white dark:bg-zinc-900 fixed z-10 w-full py-5 px-8 text-sm font-light top-0'>
                <ul className='flex items-center gap-3'>
                    <li>
                        🛒 {cart.length}
                    </li>
                </ul>
            </nav>
        )
    }
    
    
    Asi va quedando el mio: ![](https://static.platzi.com/media/user_upload/image-4dc4640f-6496-4819-a178-ea6c69cc3dbc.jpg)
    Mi diseño: ![](https://static.platzi.com/media/user_upload/image-37fa1b83-7253-42c7-9ad9-08be59bd4a9f.jpg)
    Le agregue un par de cositas, el carousel modifique un poco las card, agregue algo de color y también la respuesta responsive, al final del curso dejare el enlace del repo y del git page para que vayan a visitarlo <3 ajajajja ![](https://i.ibb.co/tPC1pqD/Captura-de-pantalla-2023-10-01-175036.png)

    Por buenas prácticas en react se recomienda usar una arro function que actualiza el estado dentro del setState en lugar de actualizar el estado con operaciones simples directas porque si es que hay más de un setState en el mismo archivo el valor real del estado se perderá y solo reflejara el resultado del primer setState. En otras palabras se debe usar el setState de esta manera…

    <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={()=>(context.setCount(***(count)=>count+1***))}>+</div>
    

    Y no de esta manera…

    <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={()=>(context.setCount(context.count + 1))}>+</div> 
    

    Fuente:

    Alguien me podría indicar por que a la hora de agregar un item me sale el mismo mensaje dos veces

    Yo quise que se le diera un feedback al usuario al agregar productos al carrito, para ello agrege un operador ternario que al momento de validar que el count es mayor que 0 agregara unas clases al elemento para que se visualize mejor.

    <li>
    	<span>💰</span>
            <span 
    		className={count == 0 ? '' : 'bg-blue-500 rounded-full text-white px-2 py-0.5 font-semibold'}
    	>
    		{count}
    	</span>
    </li>
    

    Asi vamos…

    Para los que lo hicimos con un array se me ocurrio esta manera de agregar el contador 😄

    Mis apuntes:

    tomamos el context de react, ese context lo pasamos a una variable que se termina leyendo en un componente.

    import { createContext, useState } from ‘react’

    export const ShoppingCartContext = createContext()

    export const ShoppingCartProvider = ({children}) => {

    const [count, setCount] = useState(0) // establecemos un contador inicial, y una variable que acepte los cambios en el contador
    
    
    return (
        <ShoppingCartContext.Provider value={{
            count,
            setCount
        }}>
            {children}
        </ShoppingCartContext.Provider>
    )
    

    }

    Para hacer uso del contexto, pasamos el contexto declarado a una variable en otro componente y llamamos al componente con una función:
    
      <li>
                    🛒 {context.count}
                </li>
    

    o

    import {ShoppingCartContext } from ‘…/…/Context’

    const Card = (data) => {

    const context = useContext(ShoppingCartContext) // lee el estado global del proveedor
    

    //…//
    <div
    onClick={() => context.setCount(context.count + 1)}
    >
    +
    </div>

    }

    Hola, estoy super contenta con este curso, porque he comprendido mas a profundidas los conceptos adquiridos con el profe Juan DC ()

    para los que estan usando exports nombrados, deben exportar 2 cosas

    export { ShoppingCartProvider, ShoppingCartContext }

    por aca les dejo el Store con Zustand por si no quieren usar Context, automaticamente guarda en localStorage la suma, se puede modificar para que no guarde numeros si no que el objeto añadido solo modifiquen la suma y el type o interface

    Creo que lo que más me ha gustado de este curso es lo sencillo que lo hace la profe teff. Si necesitas conocimientos previos tal como lo dijeron al inicio del curso

    Así va mi proyecto!!!

    Card component

    import { useContext } from 'react'
    import { ShoppingCartContext } from '../../context'
    
    const Card = ({ product }) => {
      const { count, setCount } = useContext(ShoppingCartContext)
      const { category, images, title, price } = product
    
      const handleClick = () => {
        setCount(count + 1)
      }
    
      return (
        <div className="bg-white cursor-pointer w-56 h-60 rounded-lg">
          <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">
              {category.name}
            </span>
            <img className="w-full h-full object-cover rounded-lg" src={images[0]} alt={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={handleClick}
            >
              +
            </div>
          </figure>
          <p className="flex justify-between">
            <span className="text-sm font-light">{title}</span>
            <span className="text-lg font-medium">${price}</span>
          </p>
        </div>
      )
    }
    
    export default Card
    
    
    mi aporte en TS: ![](https://static.platzi.com/media/user_upload/carbon%20%285%29-c52be841-38b0-4633-9b76-f1a1d6e877a5.jpg)
    así voy pero tengo problemas con el API ![](https://static.platzi.com/media/user_upload/imagen-95535f43-343b-4f75-8011-b7f80231037f.jpg)