El hook useContext
Introducción
useContext es un hook en React que permite acceder al contexto de una aplicación de manera sencilla y eficiente. El contexto se usa para compartir datos entre componentes sin necesidad de pasar props manualmente a través de cada nivel del árbol de componentes.
1. Qué es el Contexto en React? #
El contexto es como una "caja" donde puedes almacenar datos globales (como temas, idiomas, usuario autenticado, etc.) y permitir que cualquier componente acceda a esos datos, sin necesidad de pasarlos explícitamente como props.
2. Cómo funciona useContext? #
useContext simplifica el acceso al contexto en los componentes funcionales.
3. Crear y Usar un Contexto #
Paso 1: Crear el Contexto #
1import React, { createContext } from "react"; 2 3// Crear el contexto 4const TemaContext = createContext(); 5 6export default TemaContext;
Paso 2: Proveer el Contexto #
Usamos un Provider para envolver los componentes que necesitan acceso al contexto.
1import React, { useState } from "react"; 2import TemaContext from "./TemaContext"; 3import ComponenteHijo from "./ComponenteHijo"; 4 5function App() { 6 const [tema, setTema] = useState("claro"); 7 8 return ( 9 <TemaContext.Provider value={{ tema, setTema }}> 10 <div className={tema}> 11 <h1>Ejemplo con useContext</h1> 12 <ComponenteHijo /> 13 </div> 14 </TemaContext.Provider> 15 ); 16} 17 18export default App;
TemaContext.Provider: Proporciona los datos del contexto (temaysetTema) a los componentes hijos.value={{ tema, setTema }}: Los datos que estarán disponibles para los componentes que consuman el contexto.
NOTA: En React 19, ya no es necesario usar .Provider
Paso 3: Consumir el Contexto con useContext #
En un componente hijo, usamos useContext para acceder a los datos del contexto.
1import React, { useContext } from "react"; 2import TemaContext from "./TemaContext"; 3 4function ComponenteHijo() { 5 const { tema, setTema } = useContext(TemaContext); 6 7 return ( 8 <div> 9 <p>El tema actual es: {tema}</p> 10 <button onClick={() => setTema(tema === "claro" ? "oscuro" : "claro")}> 11 Cambiar Tema 12 </button> 13 </div> 14 ); 15} 16 17export default ComponenteHijo;
Explicación #
useContext(TemaContext)devuelve los valores proporcionados por elProvider.- Ahora
temaysetTemaestán disponibles directamente en el componente hijo.
4. Ejemplo Completo #
1import React, { createContext, useState, useContext } from "react"; 2 3// Crear el contexto 4const TemaContext = createContext(); 5 6// Componente principal que provee el contexto 7function App() { 8 const [tema, setTema] = useState("claro"); 9 10 return ( 11 <TemaContext.Provider value={{ tema, setTema }}> 12 <div className={`app ${tema}`}> 13 <h1>Ejemplo Completo con useContext</h1> 14 <BotonTema /> 15 </div> 16 </TemaContext.Provider> 17 ); 18} 19 20// Componente hijo que consume el contexto 21function BotonTema() { 22 const { tema, setTema } = useContext(TemaContext); 23 24 return ( 25 <button onClick={() => setTema(tema === "claro" ? "oscuro" : "claro")}> 26 Cambiar a Tema {tema === "claro" ? "Oscuro" : "Claro"} 27 </button> 28 ); 29} 30 31export default App;
Resultado #
El botón permite alternar entre los temas "claro" y "oscuro", cambiando la clase CSS del contenedor div.
5. Usos Comunes del Contexto #
- Tema de la Aplicación (Claro/Oscuro).
- Autenticación (datos del usuario autenticado).
- Idiomas (traducciones).
- Carrito de Compras (productos seleccionados).
6. Ventajas de useContext #
- Elimina la necesidad de pasar props innecesarias a través de múltiples niveles.
- Hace que el código sea más limpio y mantenible.
- Ideal para datos globales que muchos componentes necesitan.
7. Consideraciones #
-
Evitar Exceso de Contextos:
Usar muchos contextos puede hacer que el código sea difícil de mantener. Considera combinarlos cuando sea posible. -
Separar el Contexto de la Lógica:
Si el contexto tiene lógica compleja, encapsúlalo en un Custom Hook.
8. Crear un Custom Hook para Contexto #
1import React, { createContext, useState, useContext } from "react"; 2 3// Crear el contexto 4const TemaContext = createContext(); 5 6// Custom Hook para usar el contexto 7function useTema() { 8 return useContext(TemaContext); 9} 10 11// Proveedor del contexto 12function TemaProvider({ children }) { 13 const [tema, setTema] = useState("claro"); 14 15 return ( 16 <TemaContext.Provider value={{ tema, setTema }}> 17 {children} 18 </TemaContext.Provider> 19 ); 20} 21 22export { TemaProvider, useTema };
Uso del Custom Hook #
1import React from "react"; 2import { TemaProvider, useTema } from "./TemaContext"; 3 4function App() { 5 return ( 6 <TemaProvider> 7 <ComponenteHijo /> 8 </TemaProvider> 9 ); 10} 11 12function ComponenteHijo() { 13 const { tema, setTema } = useTema(); 14 15 return ( 16 <button onClick={() => setTema(tema === "claro" ? "oscuro" : "claro")}> 17 Cambiar Tema 18 </button> 19 ); 20} 21 22export default App;
Resumen del tema
Conceptos clave #
- Problema de Prop Drilling: evita la necesidad de pasar propiedades manualmente a través de niveles intermedios del árbol de componentes.
- API de Contexto (
createContext): crea un objeto de contexto que provee datos mediante<Context.Provider value={...}>(o directamente<Context value={...}>en React 19). - Consumo con
useContext(Context): hook que suscribe al componente a los cambios del contexto, re-renderizándolo cuandovaluecambia. - Patrón Provider + Custom Hook: encapsular el contexto junto con un hook personalizado (
useTema()) para abstraer validaciones de inicialización.
Qué debes recordar #
useContext permite compartir estado global (temas, usuario, carrito) directamente entre cualquier componente del árbol sin prop drilling.