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
- Puedo crear un Context con createContext() y un Provider componente que use useState
- Sé envolver mi aplicación con Providers para hacer el estado global disponible
- Puedo consumir Context en componentes hijos usando el hook useContext()
- Diferencio cuándo usar estado local (useState) vs estado global (Context)
- Implemento useEffect correctamente con array de dependencias para efectos controlados
- Evito prop drilling refactorizando componentes para usar Context
- 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.
- Crea un nuevo proyecto Expo con:
npx create-expo-app CarritoApp - 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()
- En App.js, envuelve tu aplicación con CartProvider
- 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)
- 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()
- 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
- 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.