El conocimiento es el nuevo dinero.
Aprender es la nueva manera en la que inviertes
Acceso Cursos

Angular Signals: Mejores practicas

· 5 min de lectura
Angular Signals: Mejores practicas

En este artículo, comparto mi experiencia de trabajo con Angular Signals después de casi un año utilizándolas.

¿Cuándo usar Signals?

  • En plantillas;
  • Para la gestión de estados;
  • Cuando necesitas reaccionar a cambios en un valor sin un aspecto temporal.

En plantillas Angular, las signals son mejores que los Observables: programan la Detección de Cambios sin pipes, están libres de fallos, y puedes leer la misma signal varias veces y será "gratis" en términos de rendimiento (y se garantiza que los valores leídos son los mismos).

Hay otras razones que no son tan fáciles de explicar brevemente, pero eso ya es suficiente para hacer una regla: cada variable (que pueda cambiar) en sus nuevas plantillas debe ser una signal.

Fuera de las plantillas, las signals también se pueden utilizar para la reactividad, pero, como ya he mencionado, sin un aspecto temporal.

Hay dos formas de crear variables reactivas en Angular: Observables y Signals.

Si describes en palabras, cómo tu variable debe expresar su reactividad, verás lo que necesitas usar.

Si el rol de una variable puede ser descrito como condiciones, entonces necesitas una signal:

  • "si esta variable tiene este valor, entonces muestra esta lista"
  • "si esta variable tiene este valor, este botón se desactiva"

Si la descripción de la función de una variable incluye palabras relacionadas con el tiempo, necesita un Observable:

  • "cuando el cursor se mueve..."
  • "espera al evento de carga de archivos y entonces..."
  • "cada vez que ocurra este evento, haz esto..."
  • "hasta que este evento..."
  • "durante N segundos ignorar..."
  • "después de esta petición..."

Las signals no tienen eje temporal, y no pueden retrasar un valor siempre tienen un valor, y sus consumidores deberían poder leerlo siempre.

Los consumidores de signals, computed(), effect() y plantillas no garantizan que leerán cada nuevo valor escrito en las signals que observan.

Una signal actualizada será leída eventualmente, no instantáneamente después de la actualización como ocurre con los Observables.
CPU
1 vCPU
MEMORIA
1 GB
ALMACENAMIENTO
10 GB
TRANSFERENCIA
1 TB
PRECIO
$ 4 mes
Para obtener el servidor GRATIS debes de escribir el cupon "LEIFER"

Los consumidores deciden cuándo leerán el nuevo valor utilizando sus mecanismos de programación. Puede ser "en la siguiente tarea", "durante el siguiente ciclo de detección de cambios" o en cualquier otro momento, a elección del consumidor.

¿Cuándo utilizar computed()?


¡Siempre que quieras!

computed() es lo mejor de Angular Signals, increíblemente práctico y seguro de usar. Usando computed(), harás tu código más declarativo.

Sólo hay dos reglas sobre el uso de computed():

  1. No modifique cosas en computed(). Debe calcular un nuevo resultado, eso es todo. No modifiques el DOM, no mutes variables usando esto, y no llames a funciones que puedan hacer eso.

No empuje valores a Observables - causará propagación de contexto reactivo no intencional (explicado abajo para effect()). computed() no debería tener efectos secundarios, debería ser una función pura.

2. No realice llamadas asíncronas en computed(). Esta función no permite modificar las signals (y es sorprendentemente útil), pero no puede rastrear código asíncrono.

Además, las signals de Angular son estrictamente síncronas, así que si quieres usar código asíncrono en computed(), estás haciendo algo mal. Así que, nada de setTimeout(), nada de Promesas 🙏🏼 , nada de otras cosas asíncronas.

¿Cuándo usar effect()?


Los docs de Angular dicen que raramente necesitarás effect() y desaconsejan su uso (copia, si los docs van a ser editados).

Y esa información es correcta: raramente necesitarás effect()... si tu código es declarativo ;)

Cuanto más imperativo sea tu código, más a menudo necesitarás effect(). No hay código sin partes imperativas, pero todos debemos intentar que nuestro código sea lo más declarativo posible, por lo que necesitamos usar effect() lo menos posible.

Además de los peligros, mencionados por Angular docs (bucles infinitos, errores de detección de cambios), hay otra cosa, que podría ser bastante desagradable: los efectos se ejecutan en un contexto reactivo, y cualquier código que llame en efecto, se ejecutará en un contexto reactivo 🫠. Si ese código lee algunas signals, se añadirán como dependencias a tu efecto.

Aquí Alex Rickabaugh explica los detalles.

Todavía no quiero animarte a usar effect(), pero te daré consejos sobre cómo usarlo de la forma más segura posible:

  1. La función que proporciones a effect() debe ser lo más pequeña posible. De esta forma será más fácil de leer y detectar comportamientos erróneos.
  2. Lee primero las signals, luego envuelve el resto del efecto en untracked():
effect(() => {
  // reading the signals we need
  const a = this.a();
  const b = this.b();
  
  untracked(() => {
    // rest of the code is here - this code should not
    // modify the signals we read above!
    if (a > b) {
      document.title = 'Ok';
    }
  });
});

Mezclar signals y observables en angular


...¡está bien!

Tu código tendrá signals y Observables, al menos porque las signals no pueden usarse para todo tipo de reactividad. No es un problema, está perfectamente bien.

Si necesitas algún valor de un Observable en tu computed(), crea una signal usando toSignal() (fuera de computed()).

Si necesitas leer una signal en pipe() de Observable, hay dos maneras:

Si necesitas reaccionar a los cambios de esa signal en tu Observable, entonces necesitas convertir esa signal en Observable y añadirla usando algún operador join.
Si estás seguro de que sólo necesitas el valor actual de una signal y no necesitas reaccionar a sus cambios - puedes leer una signal directamente en tus operadores o subscribe(). Observable no es un contexto reactivo, por lo que no necesitas untracked() aquí.

Fuente