Saltar al contenido

Lección 8 de 20 · Lectura y práctica

Gestión de estado con Context API y hooks (useState, useEffect)

Concepto claveLa Context API de React es un sistema de gestión de estado que permite compartir datos entre componentes sin necesidad de pasar props manualmente a través de cada nivel del árbol de componentes. Imagina que estás.

Del concepto a la práctica

Taller de esta lección

El contexto resulta apropiado cuando varias pantallas necesitan el mismo carrito; un campo como el texto provisional de un formulario debe permanecer local. Un estado mínimo puede ser una lista de líneas { id, quantity }, mientras el catálogo aporta nombre y precio.

Ejemplo resuelto

  1. Inicializa el contexto con items: [].

  2. Implementa addItem(id) que incremente la cantidad existente o inserte una línea.

  3. Calcula el contador con reduce, no con el número de productos distintos.

  4. Usa useEffect solo para sincronizar una consecuencia concreta, como registrar cambios localmente. Un error frecuente es mutar items.push(...), evitando que React detecte una nueva referencia. Corrígelo devolviendo un array nuevo con map o expansión.

Pruébalo

Añade p1 dos veces y p2 una vez. Conserva un campo local search en el catálogo.

Comprueba tu resultado

El contexto debe contener dos líneas distintas, el contador total debe ser 3 y cambiar search no debe modificar el carrito.

Reducer puro, cantidad y stock

El catálogo define p1 stock3 y p2 stock2. Esta función incrementa una unidad, rechaza ID desconocido y exceso de stock, y no modifica el array recibido.

javascript
const STOCK={p1:3,p2:2};
function agregar(items,id){
  if(!Object.hasOwn(STOCK,id)) throw new Error('Producto desconocido');
  const anterior=items.find(x=>x.id===id);
  if((anterior?.quantity??0)>=STOCK[id]) throw new Error('Sin stock');
  return anterior?items.map(x=>x.id===id?{...x,quantity:x.quantity+1}:x):[...items,{id,quantity:1}];
}

Desde [] agrega p1,p1,p2: dos líneas, tres unidades. Una cuarta incorporación de p1, después de llegar aquantity3, falla y deja el estado anterior. En Context usa createContext(null), un hook que rechace null fuera del proveedor y un reducer que devuelva el próximo estado o el error de la acción sin lanzar excepciones desde un updater de React. La función del ejemplo se prueba fuera de React; si la reutilizas dentro de un reducer, captura la validación allí y conserva el estado anterior con un resultado de error. No hagas notificaciones ni efectos secundarios dentro del updater.

Context distribuye estado y puede volver a renderizar consumidores; React.memo no impide automáticamente un cambio de contexto. Cambiar search solo modifica su estado local. No uses un efecto para recalcular unidades si reduce puede derivarlas durante render. Registrar el carrito en memoria o consola no es persistencia ni cifrado; define guardado e hidratación separados antes de prometer reinicios.

Diagrama de decisión con ramas Sí y No y un bucle que procesa cada elemento de una lista.
CursaloMapa de práctica
Cómo avanza un programa

Una condición decide qué camino ejecuta el programa. Un bucle repite una operación mientras queden elementos, y termina cuando la lista se agota. Separar ambas ideas ayuda a seguir el flujo y comprobar casos límite.

Ver la infografía en tamaño completo ↗

Concepto clave

La Context API de React es un sistema de gestión de estado que permite compartir datos entre componentes sin necesidad de pasar props manualmente a través de cada nivel del árbol de componentes. Imagina que estás construyendo una app de e-commerce móvil: el carrito de compras necesita ser accesible desde múltiples pantallas (productos, detalles, checkout). Sin Context, tendrías que pasar el estado del carrito como prop desde el componente raíz hasta cada componente hijo, creando un "prop drilling" que hace el código difícil de mantener.

Los hooks como useState y useEffect son funciones que te permiten usar estado y efectos secundarios en componentes funcionales. useState es como el cuaderno de notas de tu app: guarda datos que pueden cambiar (como el contador de items en el carrito). useEffect es tu asistente personal: se ejecuta cuando ciertas condiciones cambian (como cuando la app carga datos desde una API al montarse). Juntos, Context API y hooks forman un equipo poderoso para manejar estado global y local de manera eficiente en React Native.

Cómo funciona en la práctica

Vamos a implementar un sistema de autenticación para una app móvil. Primero, creas un Context que almacenará el estado del usuario (si está logueado o no). Luego, envuelves tu app con un Provider que hace este Context disponible para todos los componentes hijos. Finalmente, en cualquier pantalla donde necesites acceder al estado de autenticación, usas el hook useContext para leerlo.

Paso a paso: 1) Define el Context con createContext(), 2) Crea un componente Provider que use useState para manejar el estado, 3) Envuelve tu App con este Provider, 4) En los componentes hijos, usa useContext() para acceder al estado. Esto elimina la necesidad de pasar props de autenticación a través de 5-6 niveles de componentes, simplificando tu arquitectura.

Codigo en accion

Antes: Pasando props manualmente a través de componentes (prop drilling):

// App.js
export default function App() {
  const [user, setUser] = useState(null);
  return (
    
      
); } // Header.js function Header({ user }) { return ( Bienvenido {user?.name} ); } // HomeScreen.js function HomeScreen({ user }) { return ( ); }

Despues: Usando Context API para compartir estado globalmente:

// AuthContext.js
import React, { createContext, useState, useContext } from 'react';

const AuthContext = createContext();

export function AuthProvider({ children }) {
  const [user, setUser] = useState(null);
  
  const login = (userData) => {
    setUser(userData);
  };
  
  const logout = () => {
    setUser(null);
  };
  
  return (
    
      {children}
    
  );
}

export function useAuth() {
  return useContext(AuthContext);
}

// App.js
export default function App() {
  return (
    
      
        
); } // Header.js function Header() { const { user } = useAuth(); return ( Bienvenido {user?.name} ); }

Errores comunes

  • Crear Context innecesariamente: No uses Context para estado que solo un componente necesita. Usa useState local en su lugar. Context es para estado compartido globalmente.
  • Olvidar el Provider: Si usas useContext() en un componente que no está envuelto por el Provider correspondiente, obtendrás el valor por defecto (usualmente undefined). Siempre verifica que tu componente esté dentro del Provider.
  • Renders innecesarios: Cuando el estado en Context cambia, todos los componentes que usan ese Context se rerenderizan. Para optimizar, divide Contexts por dominio (ej: AuthContext, CartContext) o usa memoización con React.memo.
  • Confundir useState con useReducer: Para estado complejo con múltiples subvalores o lógica de actualización compleja, considera useReducer en lugar de múltiples useStates.
  • Efectos infinitos en useEffect: Siempre incluye un array de dependencias en useEffect. Si omites el array, el efecto se ejecutará en cada render, potencialmente creando loops infinitos.

Checklist de dominio

  1. Puedo crear un Context con createContext() y un Provider componente que use useState
  2. Sé envolver mi aplicación con Providers para hacer el estado global disponible
  3. Puedo consumir Context en componentes hijos usando el hook useContext()
  4. Diferencio cuándo usar estado local (useState) vs estado global (Context)
  5. Implemento useEffect correctamente con array de dependencias para efectos controlados
  6. Evito prop drilling refactorizando componentes para usar Context
  7. Puedo optimizar renders dividiendo Contexts por dominio funcional

Implementa un carrito de compras con Context API y hooks

En este ejercicio, crearás un sistema de carrito de compras para una app móvil de e-commerce usando Context API, useState y useEffect.

  1. Crea un nuevo proyecto Expo con: npx create-expo-app CarritoApp
  2. Crea un archivo CartContext.js que:
    • Defina un CartContext con createContext()
    • Cree un CartProvider que use useState para almacenar un array de items del carrito
    • Incluya funciones addToCart(item), removeFromCart(itemId) y clearCart()
    • Exporte el Context y un custom hook useCart()
  3. En App.js, envuelve tu aplicación con CartProvider
  4. Crea un componente ProductList.js que:
    • Muestre al menos 3 productos con nombre, precio y botón "Agregar al carrito"
    • Use useCart() para acceder a la función addToCart
    • Use useEffect para cargar productos desde un mock API (puedes usar un array estático)
  5. Crea un componente CartSummary.js que:
    • Use useCart() para mostrar el número de items en el carrito
    • Muestre el total calculado sumando los precios de todos los items
    • Incluya un botón para vaciar el carrito usando clearCart()
  6. Integra ambos componentes en tu pantalla principal y verifica que:
    • Al agregar productos, el contador del carrito aumenta
    • El total se calcula correctamente
    • Al vaciar el carrito, todos los items se eliminan
Pistas
  • Recuerda que el valor del Provider debe ser un objeto que incluya tanto el estado como las funciones para modificarlo
  • En useEffect, usa un array vacío [] como dependencia para cargar datos solo al montar el componente
  • Para calcular el total, puedes usar reduce() sobre el array de items del carrito

Evalua tu comprension

Completa el quiz interactivo de arriba para ganar XP.

Sigue con React Native con Expo: Desarrollo de Apps Nativas para iOS y Android

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.

01 / ELEGIR UNA RUTA

El próximo paso

Aprende IA mientras construyes algo que sí necesitas.

Empieza por el curso inicial o explora el catálogo para encontrar una práctica alineada con tu trabajo.