React 19 de Cero a Experto / Estado global
Context: datos en el aire del subárbol
Context es la respuesta de React al prop drilling: te deja poner un dato "en el aire" de un subárbol
—con un Provider— y que CUALQUIER descendiente lo lea directamente —con useContext—, sin props
intermedias. El recado ya no pasa de mano en mano: se pone en un tablón que todos los pisos pueden
consultar. Hoy lo construyes en vivo y, tan importante como usarlo, aprendes cuándo NO usarlo.
El tablón de anuncios del edificio
Los tres pasos de Context
Context tiene tres piezas: crear el contexto, proveerlo arriba, y consumirlo abajo. Aquí resolvemos
el prop drilling de la lección anterior —Panel y Barra ya no tocan usuario—:
Compara con el prop drilling: Panel y Barra quedaron LIMPIOS —no reciben ni reenvían nada—.
Saludo lee usuario directamente con useContext(UsuarioContext), sin importar cuántos niveles lo
separen del Provider. Cambiar el usuario en App actualiza Saludo al instante (todo consumidor
re-renderiza cuando el value del Provider cambia). El dato viaja "por el aire" del subárbol.
Context con estado y acciones
Lo habitual es proveer no solo un dato, sino también funciones para cambiarlo. Se agrupa en un objeto, y a menudo se envuelve en un hook propio para leerlo cómodamente:
type TemaContexto = { tema: "claro" | "oscuro"; alternar: () => void };
const TemaContext = createContext<TemaContexto | null>(null);
// hook propio: lee el contexto y avisa si falta el Provider
function useTema() {
const ctx = useContext(TemaContext);
if (ctx === null) throw new Error("useTema debe usarse dentro de <TemaProvider>");
return ctx;
}
function TemaProvider({ children }: { children: React.ReactNode }) {
const [tema, setTema] = useState<"claro" | "oscuro">("oscuro");
const alternar = () => setTema((t) => (t === "oscuro" ? "claro" : "oscuro"));
return <TemaContext.Provider value={{ tema, alternar }}>{children}</TemaContext.Provider>;
}
// cualquier descendiente:
function BotonTema() {
const { tema, alternar } = useTema();
return <button onClick={alternar}>Tema: {tema}</button>;
}Dos buenas prácticas aquí: agrupar el valor y sus acciones en un objeto ({ tema, alternar }), y
envolver useContext en un hook propio (useTema) que lanza si falta el Provider —así consumir el
contexto es una línea y los errores son claros—. El Provider encapsula el estado; los consumidores
solo dicen useTema().
Cuándo Context, y cuándo NO
¿Para qué tipo de datos es ideal Context y cuál es un mal uso frecuente?
Mini-reto
Construye un Context completo: 1) crea un ContadorContext que provea { cuenta, incrementar, reiniciar }
(estado + acciones) desde un ContadorProvider; 2) escribe un hook useContador que lo lea y lance
si falta el Provider; 3) monta dos componentes hermanos MUY separados en el árbol que usen useContador:
uno muestra cuenta, otro tiene los botones. Comprueba que comparten el mismo estado sin pasarse una
sola prop. Ese es el poder de Context.
Qué sigue
Context resuelve compartir datos estables. Pero para estado global que cambia seguido —o cuando quieres que solo re-rendericen los componentes que usan la parte que cambió— hay una herramienta más afilada, la favorita pragmática del ecosistema: ZUSTAND. La próxima lección la construye desde cero (sí, tu propio mini-Zustand en vivo) y luego muestra la real.