React Hook y el patrón “Observer”
Cómo integrar el patrón “Observer” cuando usamos React Hooks
English versión: https://medium.com/@ger86/react-hooks-and-the-observer-pattern-1e4274f0e5f5
La llegada de los React Hooks ha supuesto multitud de cambios en la forma en que diseñamos y programamos aplicaciones con React:
- han permitido añadir estado interno a los componentes funcionales, de modo que éstos han comenzado a sustituir a los componentes “clásicos” ;
- han fomentado el uso de un estilo declarativo de programación debido a su carácter funcional;
- y han simplificado la forma en que podemos reutilizar la lógica a lo largo de toda la aplicación, algo que empleando “Class componentes” era algo más complicado.
Es en torno a este último punto sobre el que gira este artículo: la forma en que podemos emplear los hooks para implementar algunos de los patrones de diseño más conocidos, de modo que podamos construir aplicaciones más fáciles de mantener y de escalar.
¡Vamos a ver cómo!
Introducción
Si has aterrizado en este artículo sin saber qué es un patrón de diseño trataré de resumirlo brevemente aunque te recomiendo que acudas a cualquiera de los siguientes enlaces para profundizar sobre este concepto tan importante en el desarrollo de aplicaciones:
- Head First Design Patterns (A Brain Friendly Guide)
- Design Patterns: Elements of Reusable Object-Oriented Software (Addison Wesley professional computing series)
- Mi artículo “Patrones de diseño en PHP” (que aunque esté pensado para aplicaciones desarrolladas con PHP sirve para hacerse una idea de este concepto gracias a los ejemplos que uso).
Un patrón de diseño es una solución general y reusable a un problema común dentro de un contexto determinado en el diseño de una aplicación.
Es decir, los patrones de diseño aportan soluciones a determinados problemas que aparecen de forma recurrente al plantear la arquitectura de una aplicación de modo evitándonos tener que reinventar la rueda constantemente.
Su potencia radica en que su uso y aplicación no depende del lenguaje en el que estemos desarrollando sino que, al abstraer la solución por medio de diagramas de clase, podremos implementarlos en cualquier aplicación software.
Otra de las ventajas de los patrones de diseño es que aportan un lenguaje común a la hora de comunicarse con otros desarrolladores ya que cada uno de ellos define un nombre específico para referirse a él así como los elementos que participan en la solución que propone. Esto permite que, independientemente del tipo de aplicación desarrollada o el lenguaje usado, se pueda emplear un mismo “diccionario” para referirse a determinados conceptos. De este modo, el código se “autodocumenta” permitiendo a las futuras personas involucradas en su mantenimiento identificar rápidamente la solución implementada.
React Hooks y el patrón “Observer”
En el patrón “Observer” un objeto, llamado “subject”, mantiene una lista de sus dependencias, llamadas “observers”, y las notifica automáticamente de cualquier cambio de estado, generalmente llamando a uno de sus métodos.
Gracias a este patrón podemos tener aplicaciones más desacopladas (pues los observers no necesitan acoplarse al subject) y mantenibles ya que cada Observer es independiente de los demás, de modo que un cambio en la funcionalidad de uno de ellos no implica la modificación del resto.
Su esquema UML de clases y secuencia son los siguientes:

Ahora imaginad que queremos desarrollar una aplicación en React en donde los usuarios pueden visualizar el estado del tiempo en una ciudad en diferentes sitos de la aplicación, por ejemplo, dentro de una barra lateral con sus ciudades favoritos y en un listado de ciudades.
Por tanto, tendríamos dos componentes:
FavouriteCityComponent
, para mostrar la temperatura de una ciudad dentro de lasidebar
de nuestra aplicación.CityTeaserComponent
, para mostrar la temperatura de una lista de ciudades.
Lo conveniente será que el estado del clima en una ciudad se encuentre centralizado y que ambos componentes lo reciban, es decir, “liberarles” de ser ellos quienes tengan que solicitarlo (lo que terminaría por provocar código duplicado). ¿Y cómo podemos conseguir centralizar el estado del clima en una ciudad de modo que ambos componentes se actualicen cada vez que se produce un cambio? Gracias al patrón “observer”:

Atendiendo al diagrama:
Weather
que actúa comoSubject
del patrón “observer” centralizando el estado del tiempo en una ciudad.FavouriteCity
yCityTeaser
actúan comoObservers
recibiendo por medio de su métodoonWeatherChanged
la actualización del tiempo procedente de la claseWeather
. Estos “observers” pueden solicitar ser notificados (notify
) por medio del métodoattach
del “subject”.
Teniendo claro esto, primero implementaremos el código de la clase Weather
. De cara poder definir nuevos tipos e interfaces así como poder “tipar ” los argumentos de cada método emplearé Typescript como lenguaje aunque si queréis podéis escribir vuestra propia versión en Javascript sin ningún tipo de problema.
Clase Weather
Según el diagrama, la clase WeatherSubject
deberá contar con los siguientes métodos:
attach
, de cara a que un “observer” pueda registrarse y recibir notificaciones cuando se actualice la temperatura.detach
, para permitir a los “observers” darse de baja cuando ya no deseen recibir más notificaciones de estado (y así también prevenir memory leaks provocados por mantener referencias en memoria a objetos que ya no se están usando).notify
, método que notificará a los “observers” registrados cada vez que se produzca una actualización en el clima.

- En la línea 1 estamos definiendo el tipo de los “observers” que podrán suscribirse a la clase
Weather
. Para nuestro caso será una función que actuará a modo de callback recibiendo como argumento la temperatura obtenida. - En las líneas 7 y 11 definimos el cuerpo de los método
attach
ydetach
de modo que los “observers” puedan suscribirse y desuscribirse a actualizaciones de estado. - En la línea 15 definimos el método
updateWeather
que obtiene el clima cada 1 segundo y notifica a los “observers” por medio del métodonotify
. - En la línea 33 el método
notify
recorre el array de “observers” y los invoca con la temperatura recibida.
Componente “FavouriteCity”
Nuestro componente FavouriteCity
actuará como “observer” de modo que:
- Al montarse deberá suscribirse como
observer
en la claseWeather
por medio del métodoattach
. - Al desmontarse deberá “desuscribirse” de la clase
Weather
por medio del métododettach
y así prevenir que sea invocado cuando ya no está siendo empleado.
Es aquí donde entran en acción los React Hooks. Crearemos un componente funcional que empleará dos hooks:
useState
para almacenar la temperatura actual. Además, este hook nos proporcionará una función para actualizar la temperatura actual que emplearemos dentro del callback que registraremos en el subjectWeatherSubject
.useEffect
para suscribirse y desuscribirse del subjectWeatherSubject
.

- En la línea 6 definimos un estado para el componente
FavouriteCity
que almacenará la temperatura actual y nos permitirá actualizarla mediante el métodosetCurrentTemperature
. - En la línea 8 definimos el callback que registraremos en
WeatherSubject
: una función que recibe como argumento unNumber
con la temperatura obtenida y que empleará el métodosetCurrentTemperature
para actualizar el estado del hookuseState
. - En la línea 12 mediante el hook
useEffect
nos suscribimos una vez (empleando como segundo argumento del hook un array vacío[]
) aWeatherSubject
por medio de su métodoattach
y en el momento en que el componente se desmonte nos desuscribimos mediante el métododetach
. - Finalmente en la línea 19 pintamos la temperatura que tenemos almacenada en el hook de estado
useState
.
Componente “CityTeaser”
Como habéis podido ver en el componente anterior, el patrón “Observer” nos ha permitido desacoplar la actualización del clima del componente FavouriteCity
. Además, gracias al hook useState
en apenas 20 líneas hemos resuelto el problema gracias al callback que nos proporciona para actualizar el estado.
De cara a que podáis ver cómo el hook useReducer
también se integra perfectamente con el patrón “Observer” implementaré el componente CityTeaser
de esa forma:

En este caso hemos requerido algo más de código:
- En las líneas 4 y 6 definimos la que será nuestra función
reducer
: recibirá como primer argumento el estado actual y como segundo argumento la acción que se ha lanzado representada por un objeto con la propiedadtype
y la propiedadtemperature
con el valor de la temperatura a actualizar. - En la línea 14 hacemos uso del hook
useEffect
para obtener la funcióndispatch
y a continuación definimos la funciónonTemperatureUpdated
para hacer undispatch
de la temperatura recibida cada vez queWeatherSubject
nos notifique. - Y finalmente, al igual que en la clase
FavouriteCity
, empleamos el hookuseEffect
para suscribirnos y desuscribirnos cuando el componente se monte y desmonte respectivamente.
Conclusiones
El patrón “Observer” es probablemente uno de los patrones más extendidos en el desarrollo de aplicaciones debido a las ventajas que proporciona:
- Bajo acoplamiento entre los componentes que forman la aplicación.
- Un único sentido para la transmisión de información y estado, es decir, es el
Subject
quien se encarga de controlar el estado de una determinada parte de la aplicación y de notificar a los “observers” que lo han solicitado.
Y gracias a los React Hooks es muy sencillo implementarlo en nuestras aplicaciones tal y como he tratado de mostrar en este artículo.
Espero que este artículo os haya servido para descubrir otra forma de usar los React Hooks ya que han venido para quedarse.
¿Quieres recibir más artículos como este?
Si te ha gustado este artículo te animo a que te suscribas a la newsletter que envío cada domingo con publicaciones similares a esta y más contenido recomendado: 👇👇👇