Lección 20 de 20 · Lectura y práctica
Quiz: Revisión del proyecto de e-commerce
Tipo de lección: QuizConcepto claveEn el desarrollo de aplicaciones de comercio electrónico con React Native y Expo, el concepto central es la arquitectura de componentes reutilizables que manejan estados complejos. Piensa en una.
Del concepto a la práctica
Taller de esta lección
La revisión final debe detectar inconsistencias entre modelo, interfaz y cálculo. Comprueba identificadores, cantidades, rutas y estados de pago con los mismos datos. Una respuesta correcta no dice solo que el flujo funciona: muestra la entrada y el resultado que permite repetir la comprobación.
Ejemplo resuelto
Con una línea de 3 reglas a 2,00, el subtotal es 6,00. Un descuento de 10 % equivale a 0,60 y el subtotal descontado es 5,40; no son 10 puntos porcentuales sobre el precio unitario ni 0,10 euros.
Pruébalo
Revisa datos y unidades.
Recalcula subtotal, descuento y total.
Comprueba navegación con ids reales.
Ejecuta éxito, rechazo y validación inválida.
Error frecuente: aplicar descuento dos veces al re-renderizar. Corrige calculando desde el precio base y guardando solo la regla del descuento.
Ejercicio: usa 3 × 2,00, descuento 10 % y envío 2,00.
Comprueba tu resultado
descuento 0,60; subtotal neto 5,40; total 7,40. La fórmula reproducible es 600 - Math.round(600*0.10) + 200 en céntimos.
Descuento explícito y clave final
El quiz usa un fixture separado: tres reglas a200 céntimos, descuento10% aplicado explícitamente y envío200. No reutiliza el umbral de100 ni el IVA16% del ejercicio histórico: son hipótesis distintas y ninguna tasa aquí representa normativa fiscal. Calcula desde subtotal base, redondeando una vez según la regla del laboratorio:
function totalConDescuento(cantidad){
if(!Number.isInteger(cantidad)||cantidad<=0) throw new Error('Cantidad inválida');
const subtotal=cantidad*200;
const descuento=Math.round(subtotal*0.10);
const neto=subtotal-descuento;
return {subtotal,descuento,neto,envio:200,total:neto+200};
}Con3 devuelve600,60,540,200,740; no hagas aritmética decimal escrita como 0,10 en JavaScript. Preguntas con clave: ¿descuento de3 reglas?60; ¿total con envío?740; ¿volver a renderizar aplica otro descuento?No, deriva otra vez de600; ¿checkout rechazado permite vaciar?No, conserva carrito y ofrece reintento. qty0/fraccionaria se rechaza.
Incluye evidencia de rutas con IDs, stock, formulario, hidratación y los tres modos de checkout; respuestas correctas no sustituyen el recorrido. Indica entrada/salida y ejecutado/pendiente. Ni una notificación ni una captura de confirmación simulada demuestra cobro real. La precisión de cálculo, identidad y confirmación evita que interfaz y modelo cuenten historias distintas.

Mapa de prácticaEl servidor concede acceso a partir de un evento verificado del proveedor y un registro persistente. La pantalla de éxito del navegador es una notificación, no una prueba suficiente de pago. La idempotencia evita duplicar la operación cuando el evento llega más de una vez.
Ver la infografía en tamaño completo ↗Tipo de lección: Quiz
Concepto clave
En el desarrollo de aplicaciones de comercio electrónico con React Native y Expo, el concepto central es la arquitectura de componentes reutilizables que manejan estados complejos. Piensa en una tienda física: tienes diferentes secciones (productos, carrito, checkout) que funcionan de manera independiente pero se comunican entre sí. En React Native, cada pantalla es un componente que gestiona su propio estado local, mientras que herramientas como Context API o Redux actúan como el "gerente de tienda" que coordina información global como el carrito de compras.
La clave está en separar la lógica de negocio de la interfaz de usuario. Imagina que estás construyendo un mostrador de pago: la pantalla muestra los productos (UI), pero el cálculo de impuestos y descuentos (lógica) debe estar en funciones separadas. Esto no solo hace el código más mantenible, sino que también facilita las pruebas y futuras actualizaciones.
Cómo funciona en la práctica
Vamos a implementar un carrito de compras paso a paso. Primero, crea un contexto para manejar el estado global del carrito. Luego, desarrolla componentes específicos: ProductCard para mostrar items, CartScreen para listar productos seleccionados, y CheckoutButton para procesar la compra. Cada componente debe recibir solo los datos que necesita, evitando acoplamientos innecesarios.
Paso 1: Configura el contexto del carrito con useReducer para manejar acciones como agregar, eliminar o actualizar cantidades. Paso 2: Crea un servicio API que se comunique con tu backend para verificar inventario y precios en tiempo real. Paso 3: Implementa navegación entre pantallas usando React Navigation, asegurando una experiencia fluida. Paso 4: Añade persistencia local con AsyncStorage para que el carrito sobreviva a cierres de la app.
Código en acción
Aquí tienes un ejemplo funcional del contexto del carrito:
// CartContext.js
import React, { createContext, useReducer, useContext } from 'react';
const CartContext = createContext();
const cartReducer = (state, action) => {
switch (action.type) {
case 'ADD_ITEM':
const existingItem = state.items.find(item => item.id === action.payload.id);
if (existingItem) {
return {
...state,
items: state.items.map(item =>
item.id === action.payload.id
? { ...item, quantity: item.quantity + 1 }
: item
),
};
}
return { ...state, items: [...state.items, { ...action.payload, quantity: 1 }] };
case 'REMOVE_ITEM':
return {
...state,
items: state.items.filter(item => item.id !== action.payload),
};
case 'CLEAR_CART':
return { ...state, items: [] };
default:
return state;
}
};
export const CartProvider = ({ children }) => {
const [state, dispatch] = useReducer(cartReducer, { items: [] });
return (
{children}
);
};
export const useCart = () => useContext(CartContext);Y así se usa en un componente de producto:
// ProductCard.js
import React from 'react';
import { View, Text, Button } from 'react-native';
import { useCart } from './CartContext';
const ProductCard = ({ product }) => {
const { dispatch } = useCart();
const handleAddToCart = () => {
dispatch({ type: 'ADD_ITEM', payload: product });
};
return (
{product.name}
Precio: ${product.price}
);
};
export default ProductCard;Errores comunes
- Manejo ineficiente del estado global: Usar solo useState en componentes padres y pasar props en cadena (prop drilling). Solución: Implementa Context API o Redux para estados compartidos.
- Falta de validación en el carrito: Permitir cantidades negativas o agregar productos sin stock. Solución: Añade verificaciones en el reducer y sincroniza con el backend.
- Navegación desorganizada: Crear stacks de navegación anidados sin una estructura clara. Solución: Planifica rutas principales (Home, Productos, Carrito, Perfil) y usa navegación anidada solo cuando sea necesario.
- Olvidar la persistencia: El carrito se vacía al cerrar la app. Solución: Integra AsyncStorage para guardar y recuperar el estado.
- No optimizar imágenes: Usar imágenes de alta resolución sin comprimir, ralentizando la app. Solución: Usa servicios como Cloudinary o comprime assets localmente.
Checklist de dominio
- ¿Implementaste un contexto global para manejar el estado del carrito?
- ¿Tus componentes son reutilizables y reciben solo los props necesarios?
- ¿Validaste datos como precios y stock antes de procesar compras?
- ¿Configuraste navegación fluida entre pantallas de productos, carrito y checkout?
- ¿Añadiste persistencia local para mantener el carrito entre sesiones?
- ¿Optimizaste imágenes y assets para rendimiento en dispositivos móviles?
- ¿Probaste la app en ambos emuladores (iOS y Android) para asegurar compatibilidad?
Refactoriza el carrito de compras para incluir descuentos
En este ejercicio, mejorarás la lógica del carrito para aplicar descuentos basados en reglas de negocio. Sigue estos pasos:
- Abre tu archivo CartContext.js y modifica el reducer para manejar un nuevo tipo de acción: 'APPLY_DISCOUNT'.
- Crea una función calculateTotal que sume los precios de los items, aplique descuentos (por ejemplo, 10% si el total supera $100) y calcule impuestos (supón 16% IVA).
- Actualiza el estado para incluir total, descuento e impuestos como propiedades separadas.
- En el componente CartScreen, muestra el desglose: subtotal, descuento, impuestos y total final.
- Añade un botón que permita aplicar un código de descuento (puede simularse con un texto fijo por ahora).
Entrega el código del reducer actualizado y el componente CartScreen.
Pistas
- Usa un switch case adicional en el reducer para 'APPLY_DISCOUNT'
- Considera almacenar el porcentaje de descuento en el estado
- Recuerda recalcular el total cada vez que cambien items o descuentos
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.
Sigue con React Native y Expo: Interfaces, Estado y APIs de Dispositivo
Esta lección forma parte de un curso de Cursalo. Revisa su programa y elige entre la compra individual o el acceso a toda la escuela.
Si ya tenías acceso a este curso, entra con tu cuenta: tus derechos y tu progreso se conservan. No necesitas comprarlo de nuevo.