Innusual Logo
Gestión del estado con Signals en Angular

innusual

Gestión del estado con Signals en Angular

Las Signals son uno de los cambios más significativos en Angular de los últimos años, con un nuevo enfoque de reactividad que afecta tanto al framework, como a las librerías que utilizamos con él.

La reactividad en JavaScript ha evolucionado constantemente desde sus inicios. Inicialmente, las actualizaciones del DOM se realizaban manualmente, lo que resultaba en un código complejo y propenso a errores. Con la llegada de AJAX en los 2000, fue posible realizar solicitudes asincrónicas sin recargar la página, mejorando la interactividad. Más tarde, las Promises facilitaron el manejo de operaciones asincrónicas, simplificando el control de flujo en casos complejos. También, el uso de objetos Proxy ha permitido crear mecanismos reactivos que detectan y responden a cambios en los objetos, brindando una manera eficiente de gestionar el estado de la aplicación.

Reactividad en Angular

Actualmente, nos encontramos en la era de los frameworks. Éstos han buscado formas de facilitar el trabajo de los desarrolladores en lo que respecta a la reactividad. Angular aportó nuevos enfoques:

  • Enlace de datos bidireccional: Esto comenzó con AngularJS y permitía que los cambios en el modelo de datos se reflejaran en el DOM (una dirección) y que los eventos del DOM provocaran acciones en el modelo de datos (la otra dirección). Lo primero fue posible gracias a la detección de cambios y a Zone.JS, que Angular introdujo como un sistema optimizado para detectar cambios en nuestros modelos de datos, utilizando Zone.JS para interceptar y rastrear todo tipo de tareas asíncronas (eventos, promesas, llamadas HTTP, etc.).
  • RxJS: Angular adoptó esta librería y la integró completamente en el framework; éste no se puede entender sin RxJS. Gracias a los Observables y sus diferentes operadores, los desarrolladores tienen una forma robusta y eficiente de trabajar con datos asíncronos y complejos, logrando un código mucho más predecible y reactivo.

Sin embargo, estos enfoques presentan algunos problemas. La detección de cambios puede generar problemas de rendimiento en aplicaciones grandes, por lo que Angular siempre ha tenido la fama de ser un framework lento. Aunque contaba con la detección de cambios OnPush, que restringía las condiciones para iniciar un ciclo de detección y no actualizaba todos los componentes a la vez si no era necesario, todos sabemos que la mayoría de los proyectos ignoran esta posibilidad y utilizan la detección de cambios por defecto.

Con RxJS sucede algo similar; aunque en los últimos años se ha notado que cada vez más personas utilizan Observables y Subjects en su código, muchas veces sigue siendo de forma no deseada. Se realizan muchas suscripciones manuales con posibles fugas de memoria y se ve un uso nulo de operadores más allá de filter, map y switchMap. No podemos olvidar a aquellos que ignoran por completo RxJS y lo utilizan únicamente cuando el framework lo exige. La razón es obvia: RxJS tiene una curva de aprendizaje difícil de gestionar para muchos desarrolladores, especialmente en un mundo de consultoría frenético, con fechas de entrega siempre próximas.

Introducción de Signals

Las primeras discusiones sobre Signals en Angular aparecieron en 2022 con el RFC del equipo en GitHub. Estas se introdujeron por primera vez en Angular 16 de manera experimental. Aunque esta nueva forma de enfocar la reactividad no es realmente algo nuevo, sino que es muy parecida a las runas de Svelte, lanzadas en 2016, o a la reactividad en Vue.JS. Una Signal es una variable cuyo valor puede cambiar en el tiempo y su cambio provoca la actualización de otras Signals dependientes. Los beneficios son claros:

  • Simplicidad: No necesitamos lidiar con suscripciones ni operadores de RxJS, y tampoco con la asincronía.
  • Eficiencia: Las Signals no requieren detección de cambios y pueden actualizar valores de forma más granular.
  • Depuración: La depuración de observables siempre ha sido un dolor de cabeza, ya que conocer el valor actual es complicado si no se sigue el flujo desde el comienzo. Esto no sucede con las Signals porque estas siempre tienen un valor definido fácil de inspeccionar.

Si quieres conocer más sobre las Signals, te recomiendo consultar la documentación oficial

Gestión del estado con Signals

Aunque solemos pensar en la gestión del estado global de nuestras aplicaciones, el estado de un único componente o servicio también debe gestionarse; a esto lo llamaremos gestión de estado localizado.

Gestión de estado localizado

Gracias a las Signals, en los componentes ya no necesitaremos implementar OnChanges ni convertir nuestros @Input en setters para detectar cambios. Tampoco será necesario utilizar observables tan a menudo (por desgracia, las Signals aún no están integradas en módulos de Angular como el redireccionamiento o los formularios reactivos). En caso de necesitarlo, gracias a @angular/core/rxjs-interop, podremos convertir Observables a Signals fácilmente. En cuanto a servicios, lo mismo ocurre; nuestras propiedades no reactivas y Subjects pueden ser convertidos a Signals sin dificultad.

Sin embargo, no debemos emocionarnos convirtiendo todo a Signals; los operadores de RxJS pueden ser muy útiles para ciertos casos de uso, y las llamadas externas a través de HttpClient no siempre pueden ser convertidas. La idea es que tanto Signals como RxJS convivan en un mismo proyecto, siendo utilizados cada uno según sus características: RxJS para flujos asíncronos y complejos que se benefician del uso de operadores, y Signals para propiedades reactivas síncronas con lógica accesible sin operadores; mientras que utilizamos el paquete de interoperabilidad para la conversión entre ambos tipos de datos.

Gestión del estado global

Las librerías de gestión de estado global más utilizadas en Angular son NGRX y NGXS. Ambas intentan implementar el patrón FLUX con sus respectivas aproximaciones.

NGXS Store

Esta librería nos ofrece el paquete @ngxs/store y tras la salida de Signals, han sido rápidos para adaptar su solución a este nuevo paradigma. Se ha incluido un nuevo método “selectSignal” para que los selectores del estado sean de tipo Signal en lugar de Observables.

NGRX

En este caso, la librería nos ofrece varios paquetes para dos tipos de gestión. La gestión de estado por patrón FLUX con @ngrx/store y @ngrx/effects, y otra gestión más reducida y simple para sustituir los servicios con Subjects, que sería @ngrx/component-store. En ambos casos se ha incluido un nuevo método para que los selectores devuelvan una Signal en lugar de Observables, llamado “selectSignal”.

Además de estas adaptaciones, el equipo de NGRX ha creado un nuevo paquete, @ngrx/signals, donde el estado es un Signal en sí y no hay dependencia alguna con RxJS. Y al igual que antes, en este caso contamos con la SignalStore para estados complejos y SignalState para aquellas gestión más simple y ligera.

Conclusión

Está claro que las Signals son uno de los cambios más significativos en Angular de los últimos años. Este nuevo enfoque de reactividad afecta tanto al framework como a las librerías que utilizamos con él. Poco a poco, todos los módulos de Angular irán incorporando el uso de Signals, al igual que las librerías más populares. Esto apunta a un futuro sin Zone.JS ni detección de cambios, aportando ventajas como la mejora del rendimiento, la reducción de la carga inicial al eliminar las dependencias de Zone.JS y posiblemente de RxJS, así como la simplificación del proceso de depuración en caso de errores.

¿Y tú? ¿Has probado ya las Signals?

>>> Podría interesarte

    Accesibilidad EAA (European Accessibility ACT)

    Javier Rubio Honrado

    La accesibilidad digital mejora la experiencia de todos los usuarios, permitiendo un acceso más equitativo a los servicios. La Ley Europea de Accesibilidad (EAA) busca garantizar que los productos y servicios digitales sean inclusivos, estableciendo requisitos claros para su implementación.

    Optimiza el rendimiento y SEO de tu web

    Enzo Andrés García Ramírez

    Elige la mejor técnica de renderizado entre SPA vs SSR vs SSG para optimizar el rendimiento y SEO de tu aplicación web.

    Gestión del estado con Signals en Angular

    innusual

    Las Signals son uno de los cambios más significativos en Angular de los últimos años, con un nuevo enfoque de reactividad que afecta tanto al framework, como a las librerías que utilizamos con él.