Cómo tener contadores de cantidad independientes en un sitio de comercio electrónico

En el desarrollo de aplicaciones de comercio electrónico, es común que los desarrolladores se enfrenten a desafíos relacionados con el manejo del estado, especialmente cuando se trata de contadores de cantidad en los productos del carrito de compras. En esta entrada, abordaremos cómo implementar contadores de cantidad independientes para cada producto en un carrito, lo que permite a los usuarios modificar la cantidad de un artículo sin afectar a los demás. Vamos a profundizar en el uso de hooks y contextos en React para lograr esto.

Problema del contador de cantidad

En un componente de resumen del carrito, donde se manejan múltiples productos, cada producto debería tener su propio contador de cantidad. Sin embargo, muchos desarrolladores encuentran que al intentar actualizar la cantidad de un producto, todos los contadores se actualizan simultáneamente. Esto se debe a que se está utilizando un estado compartido, lo que provoca un comportamiento no deseado en la interfaz de usuario.

Implementación del hook useQuantityCounter

Para solucionar este problema, es esencial que cada contador de cantidad gestione su propio estado. A continuación, se muestra cómo se puede implementar un hook personalizado useQuantityCounter que permita incrementar y decrementar la cantidad de manera independiente:

import { useCart } from "../_context/useCart";

export function useQuantityCounter(minQty = 1, maxQty = 99) {
  const { qty, setQty } = useCart();

  function increment() {
    setQty((prev) => (prev < maxQty ? prev + 1 : prev));
  }

  function decrement() {
    setQty((prev) => (prev > minQty ? prev - 1 : prev));
  }

  return { qty, increment, decrement };
}

Componente QuantityCounter

A continuación, se presenta el componente QuantityCounter que utiliza el hook anterior para permitir la modificación de la cantidad del producto. Este componente genera un botón para incrementar y otro para decrementar la cantidad, mostrando siempre el valor actual.

import { useQuantityCounter } from "../../_hooks/useQuantityCounter";

function QuantityCounter() {
  const { qty, increment, decrement } = useQuantityCounter();
  return (
    <div className="flex items-center">
      <h2>Cantidad</h2>
      <div className="w-auto px-4 md:w-1/6 lg:w-2/12">
        <div className="inline-flex items-center px-4 font-semibold text-gray-500 border border-gray-200 rounded-md">
          <button className="hover:text-gray-700" onClick={decrement}>-</button>
          <input
            className="w-12 px-2 justify-center text-center border-0 rounded-md bg-gray-50 py-1.5"
            value={qty}
            readOnly
          />
          <button className="hover:text-gray-700" onClick={increment}>+</button>
        </div>
      </div>
    </div>
  );
}

export default QuantityCounter;

Manejo del estado en el contexto del carrito

Para asegurarnos de que cada QuantityCounter tenga su propio estado, podemos crear una estructura que respalde este manejo. En el contexto useCart, se puede almacenar el estado relacionado con cada producto de la siguiente manera:

const [qty, setQty] = useState({ /* inicializar con valores por producto */ });

Componente CartProducts

A continuación, se muestra cómo se puede integrar el componente QuantityCounter dentro de un componente de productos del carrito. Esto permite que cada producto en el carrito tenga su propia lógica para manejar la cantidad:

import { useCart } from "../../../_context/useCart";
import QuantityCounter from "../../UI/QuantityCounter";

function CartProducts({ src, alt, name, description, price, size }) {
  const { qty } = useCart();
  return (
    <div>
      <div className="flex items-center mb-6">
        <img src={src} alt={alt} />
        <h2>{name}</h2>
        <p>{description}</p>
        <QuantityCounter />
        <p>{price * qty}</p>
      </div>
    </div>
  );
}

export default CartProducts;

Resumen del carrito

Finalmente, en el componente que resume el carrito, se puede iterar a través de los productos y renderizar cada uno con su contador de cantidad correspondiente.

function CartSummary() {
  const { cart } = useCart();
  if (cart.length === 0) {
    return (<h1>El carrito está vacío</h1>);
  }

  return (
    <div>
      {cart.map((product, i) => (
        <CartProducts
          key={i}
          src={product.image}
          alt={product.product_name}
          name={product.product_name}
          description={product.product_description}
          price={product.price}
          size={product.size}
        />
      ))}
    </div>
  );
}

export default CartSummary;

Conclusión

Crear contadores de cantidad independientes en un sitio de comercio electrónico es crucial para mejorar la experiencia del usuario. Al implementar hooks personalizados y gestionar el estado de manera eficiente, se puede lograr que cada producto en el carrito se comporte de manera independiente. Esto no solo mejora la funcionalidad de la aplicación, sino que también contribuye a una experiencia de compra más fluida y atractiva para los usuarios.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *