
Crear contextos, providers y combinar con useReducer.
Context básico
createContextcrea un contenedor de datos.Providerenvuelve la app y comparte el estado.useContextconsume la información.- Conviene definir un valor inicial y un custom hook para simplificar el consumo.
- Si el contexto es obligatorio, lanzar error si se usa fuera del Provider.
¿Cuándo usar Context?
- Para datos globales reales: tema, auth, idioma, permisos, carrito.
- Evita usarlo para estados muy locales; puede generar renders innecesarios.
- Si solo dos componentes comparten datos, props puede ser mas simple.
Composición de providers
- Se pueden anidar multiples providers en un componente
AppProviders. - Ayuda a mantener
main.jsxlimpio y ordenado. - Prioriza providers con menos cambios arriba para evitar renders masivos.
Context para autenticación
- Centraliza login, logout y usuario actual.
- Permite proteger rutas con la misma fuente de verdad.
- Guarda el estado de "cargando" mientras valida sesion.
- Puede incluir roles/permisos para habilitar secciones.
Context + useReducer
- Útil para estados complejos como un carrito.
- La lógica se organiza por acciones.
- Define un
initialStatey acciones claras (ADD, REMOVE, UPDATE). - Mantener el reducer puro facilita testing y depuracion.
Buenas prácticas y rendimiento
- Separa contextos por dominio para evitar renders globales.
- Memoiza el
valuedel Provider cuando depende de objetos. - Evita pasar funciones inline que cambien en cada render.
Ejemplos de Código
3 ejemplos
Context básico
javascript
1import { createContext, useContext, useState } from "react";
2
3const ThemeContext = createContext();
4
5export function ThemeProvider({ children }) {
6 const [theme, setTheme] = useState("light");
7 const toggleTheme = () => setTheme((t) => (t === "light" ? "dark" : "light"));
8
9 return (
10 <ThemeContext.Provider value={{ theme, toggleTheme }}>
11 {children}
12 </ThemeContext.Provider>
13 );
14}
15
16export function useTheme() {
17 return useContext(ThemeContext);
18}Auth con Context
javascript
1import { createContext, useContext, useEffect, useState } from "react";
2
3const AuthContext = createContext();
4
5export function AuthProvider({ children }) {
6 const [user, setUser] = useState(null);
7
8 useEffect(() => {
9 const saved = localStorage.getItem("user");
10 if (saved) setUser(JSON.parse(saved));
11 }, []);
12
13 const login = (userData) => {
14 setUser(userData);
15 localStorage.setItem("user", JSON.stringify(userData));
16 };
17
18 const logout = () => {
19 setUser(null);
20 localStorage.removeItem("user");
21 };
22
23 return (
24 <AuthContext.Provider value={{ user, login, logout }}>
25 {children}
26 </AuthContext.Provider>
27 );
28}
29
30export function useAuth() {
31 return useContext(AuthContext);
32}Reducer global
javascript
1import { createContext, useContext, useReducer } from "react";
2
3const CartContext = createContext();
4
5function reducer(state, action) {
6 switch (action.type) {
7 case "ADD":
8 return { ...state, items: [...state.items, action.payload] };
9 case "CLEAR":
10 return { ...state, items: [] };
11 default:
12 return state;
13 }
14}
15
16export function CartProvider({ children }) {
17 const [state, dispatch] = useReducer(reducer, { items: [] });
18
19 return (
20 <CartContext.Provider value={{ state, dispatch }}>
21 {children}
22 </CartContext.Provider>
23 );
24}
25
26export function useCart() {
27 return useContext(CartContext);
28}Recursos
3 recursos disponibles
¡Hora de Practicar!
PrácticaIntermedio15 min
Práctica guiada - Theme + Auth
Práctica
Implementar tema claro/oscuro y login con Context.
Desafío de Código
EjercicioIntermedio15 min
Ejercicios - Carrito global
Ejercicios
(1) Agregar items, (2) eliminar items, (3) total acumulado.