Compartir estado entre múltiples componentes es uno de los retos más frecuentes al construir aplicaciones con React. Cuando un componente necesita estar al tanto de lo que sucede en otro, el estado local deja de ser suficiente y es momento de implementar un estado global. A continuación se explica paso a paso cómo lograrlo utilizando React Context junto con el patrón provider, construyendo un sistema de notificaciones como caso práctico.
¿Por qué necesitamos un estado global con React Context?
En React existen dos grandes categorías de estado: el estado local, que vive dentro de un solo componente, y el estado global, que puede ser leído y modificado desde cualquier parte de la aplicación. React Context es una de las formas nativas de implementar ese estado global sin depender de librerías externas.
El ejemplo trabajado es un sistema de transacciones [0:08] que contiene:
- Una vista que pregunta si el usuario está listo para confirmar.
- Un botón de confirmación.
- Un componente de notificación que muestra si la transacción fue exitosa.
El componente de notificación debe reaccionar a lo que ocurre en la vista de confirmación, y esa comunicación entre componentes distantes es exactamente lo que justifica el uso de React Context [1:00].
¿Cómo se crea el provider de notificaciones paso a paso?
El patrón provider consiste en crear un componente que envuelve (wrapper) a toda la aplicación y le provee acceso al estado global. La implementación comienza creando la estructura del proyecto con Vite [1:20]:
- Se ejecuta
npm create vite con el nombre del proyecto.
- Se selecciona React con TypeScript.
- Se instalan dependencias con
npm install y se levanta el servidor con npm run dev.
Dentro de la carpeta src, se crea una carpeta llamada context y dentro de ella el archivo NotificationContext.tsx [2:42].
¿Qué contiene el notification provider?
El notification provider es una función que maneja dos responsabilidades principales: mostrar y ocultar la notificación [3:18]. Para ello se define un estado local con useState:
tsx
const [message, setMessage] = useState<string | null>(null);
Luego se crean dos funciones:
hideNotification: establece el mensaje en null, ocultando la notificación [4:08].
showNotification: recibe un message de tipo string, lo asigna al estado y programa su ocultamiento automático con setTimeout después de tres segundos [4:30].
tsx
const showNotification = (message: string) => {
setMessage(message);
setTimeout(() => {
hideNotification();
}, 3000);
};
¿Cómo se define el contexto con createContext?
Para que el estado sea accesible globalmente, se utiliza createContext [5:22]. Se exporta una variable que contiene el contexto creado:
tsx
export const notificationContext = createContext<
NotificationContextType | undefined
(undefined);
El tipo NotificationContextType define la forma del estado global [6:10]:
tsx
type NotificationContextType = {
message: string | null;
showNotification: (message: string) => void;
hideNotification: () => void;
};
Estos tres campos permiten que cualquier componente pueda leer el mensaje, disparar una notificación o cerrarla manualmente.
¿Cómo se conecta el provider con la aplicación?
El return del notification provider utiliza notificationContext.Provider como componente envolvente [7:40]. Se le pasa un value con las tres propiedades definidas:
tsx
return (
<notificationContext.Provider
value={{ message, showNotification, hideNotification }}
</notificationContext.Provider>
);
El parámetro children con tipo React.ReactNode permite que cualquier componente hijo pueda ser envuelto por este provider y acceder al estado global [8:20].
Con esto queda listo el proveedor. El siguiente paso es crear un custom hook que utilice useContext para simplificar la lectura del estado desde los demás componentes de la aplicación [9:10]. De esta manera, cada componente podrá suscribirse al contexto de notificaciones de forma limpia y reutilizable.
¿Has implementado React Context en tus proyectos o prefieres usar otras soluciones para el estado global? Comparte tu experiencia.