Scroll to top
© 2022, SYNTONIZE Digital Pulse

Angular Signals: La Nueva Era de la Reactividad en Angular

Índice

Introducción a Angular Signals

Si llevas tiempo trabajando con Angular, sabes que la reactividad ha estado dominada por RxJS. No hay duda de que los Observables son poderosos, pero también pueden volverse complejos y difíciles de manejar en proyectos grandes.

Con Angular 18 y 19, el equipo de Angular nos trae Angular Signals, una nueva forma de manejar el estado en la UI de forma más intuitiva y eficiente. Pero esto plantea varias preguntas:

¿Cómo se compara con RxJS?

¿Es realmente más eficiente?

¿Cómo se integra con otros paradigmas de reactividad en otros frameworks?

En este artículo exploraremos qué son las Signals, sus ventajas, diferencias con RxJS y otros frameworks, buenas prácticas para su implementación y cómo pueden mejorar nuestras aplicaciones modernas en Angular.

¿Qué son las Angular Signals?

Las Signals son una nueva API en Angular que permite gestionar estado de manera reactiva y eficiente sin necesidad de suscripciones manuales. Piensa en ellas como contenedores de valores reactivos que notifican automáticamente a los consumidores cada vez que cambian.

Si has usado BehaviorSubject o ReplaySubject en RxJS para manejar estado, Signals simplifican este proceso al eliminar la necesidad de suscripciones y operadores complejos.

Principales ventajas de Angular Signals:

  • Más eficientes: Angular rastrea exactamente qué partes de la UI dependen de qué valores y actualiza solo lo necesario.
  • Menos código boilerplate: Se acabaron las suscripciones manuales y la necesidad de unsubscribe().
  • Más predecibles: No hay que preocuparse por cuándo se dispara un .next() o si una suscripción quedó abierta.
  • Mejor rendimiento: Signals reducen el trabajo innecesario en el ChangeDetection, lo que mejora la velocidad de renderizado.
  • Compatibles con RxJS: Si ya usas Observables, puedes integrarlos fácilmente con Signals.

Comparación: Angular Signals vs. Otros Modelos de Reactividad

Cada framework moderno maneja la reactividad de manera diferente. ¿Cómo se comparan las Signals de Angular con otras soluciones populares?

Característica

Angular Signals

RxJS (Angular)

React (useState + useEffect)

Vue (reactive, ref, computed)

SolidJS (Reactivity Core)

Complejidad

Baja

Alta

Media

Media

Baja

Rendimiento

Alto

Medio

Medio

Alto

Muy alto

Dependencias

Ninguna

RxJS

React Hooks

Vue Composition API

Reactivity Core nativo

Flujos asíncronos

Limitado

Potente

Depende de useEffect

Integrado en Vue

Integrado

Facilidad de uso

Alta

Baja

Media

Alta

Alta

  • Vs. React (useState + useEffect)
    React usa useState para manejar estado local y useEffect para efectos secundarios. Signals eliminan la necesidad de dependencias y optimizan automáticamente el renderizado, algo que en React requiere memoization manual.
  • Vs. Vue (reactive, ref, computed)
    Vue tiene un modelo de reactividad muy parecido al de Signals (ref, computed). Sin embargo, Signals tienen mejor integración con el renderizado de Angular y eliminan trabajo innecesario en el DOM.
  • Vs. SolidJS
    SolidJS es probablemente lo más cercano a Signals en términos de eficiencia y optimización granular. Ambos sistemas eliminan re-renderizados innecesarios, pero SolidJS lo hace a nivel de compilación, mientras que Angular Signals opera en tiempo de ejecución.
  • Vs. RxJS
    Si bien RxJS sigue siendo clave para flujos de datos complejos y asíncronos, Signals son más intuitivas y eficientes para el estado de UI, eliminando la necesidad de suscripciones y operadores extra.

Buenas Prácticas y Patrones con Angular Signals

Signals pueden hacer nuestro código más limpio y eficiente, pero también hay formas incorrectas de usarlas. Aquí algunos consejos clave:

1. Usa Signals para estado local, no para todo

Si bien Signals son potentes, no son una solución global para manejar estado en toda la aplicación. Usa Signals para estado reactivo en componentes y mantenlo separado de la lógica de negocio.

Mal uso (convertir todo el estado de la app en Signals)

export class StoreService {
  users = signal<User[]>([]);
  isLoading = signal(false);
}

 

Buen uso (usar Signals solo donde realmente se necesiten)

export class StoreService {
 users = signal<User[]>([]);
 isLoading = signal(false);
}
}

2. No abuses de las Signals anidadas

Si necesitas almacenar objetos dentro de una Signal, evita mutarlos directamente.

Mutar directamente el estado (rompe la reactividad)

userSignal().name = "Nuevo Nombre"; // NO HACER ESTO

Actualizar el estado correctamente

userSignal.set({ ...userSignal(), name: "Nuevo Nombre" });

3. Usa computed() para cálculos derivados

Si necesitas un valor derivado, usa computed() en lugar de recalcularlo manualmente.

import { computed, signal } from '@angular/core';

const price = signal(100);
const tax = signal(0.16);
const total = computed(() => price() * (1 + tax()));

console.log(total()); // 116

4. Usa efectos (effect) con cuidado

effect() es útil para ejecutar código en respuesta a cambios de Signals, pero evita usarlo para lógica de negocio pesada.

import { effect } from '@angular/core';

effect(() => {
 console.log("El total ha cambiado:", total());
});

5. Combina Signals con RxJS cuando sea necesario

Si ya usas RxJS en tu aplicación, no intentes reemplazarlo por completo. Usa Signals para estado de UI y RxJS para flujos de datos asíncronos.

import { toSignal } from '@angular/core/rxjs-interop';
import { of } from 'rxjs';

const observable$ = of(42);
const signalValue = toSignal(observable$);
console.log(signalValue()); // 42

Ejemplos Prácticos y Casos de Uso Avanzado

Hasta ahora hemos hablado de qué son las Signals y cómo pueden hacer nuestro código más limpio y eficiente. Pero, ¿cómo se usan en situaciones reales? Aquí algunos ejemplos prácticos avanzados.

1. Uso de Signals en un Store Global

En aplicaciones grandes, necesitamos manejar estado compartido entre múltiples componentes. Con Signals, podemos construir un store global sin necesidad de NgRx o servicios con BehaviorSubject.

import { Injectable, signal } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class CounterStore {
 count = signal(0);

 increment() {
 this.count.set(this.count() + 1);
 }

 decrement() {
 this.count.set(this.count() - 1);
 }
}

Uso en un componente:

import { Component, inject } from '@angular/core';
import { CounterStore } from './counter.store';

@Component({
 selector: 'app-counter',
 template: `


Contador: {{ counterStore.count() }}


 `,
})
export class CounterComponent {
 counterStore = inject(CounterStore);
}

  • No requiere suscripciones ni ngOnDestroy.
  • Optimización automática del renderizado.
  • Menos código comparado con NgRx o un servicio basado en RxJS.

2. Uso de Signals en Formularios Reactivos

Uno de los retos en Angular es manejar formularios reactivos de manera eficiente. Con Signals, podemos mejorar la reactividad sin depender de observables.

Ejemplo: Sincronización de un formulario con Signals

import { Component } from ‘@angular/core’;
import { FormControl, FormGroup } from ‘@angular/forms’;
import { signal, computed } from ‘@angular/core’;

@Component({
  selector: ‘app-login’,
  template: `
    <form [formGroup]=»form«>
      <input formControlName=»email» placeholder=»Email»>
      <input formControlName=»password» type=»password» placeholder=»Contraseña»>
    </form>
    <p>Formulario válido: {{ isValid() }}</p>
  `,
})
export class LoginComponent {
  form = new FormGroup({
    email: new FormControl(»),
    password: new FormControl(»),
  });

  isValid = computed(() => this.form.valid);

Ventaja: computed() mantiene la reactividad sin necesidad de suscripciones a valueChanges.

3. Uso de Signals en Angular Router

Ahora podemos usar Signals para reaccionar a cambios de parámetros en la URL sin necesidad de suscribirse a ActivatedRoute.params.

Ejemplo: Obtención de un parámetro de la URL

import { Component, inject } from '@angular/core';
import { signal } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
 selector: 'app-product',
 template: `Producto ID: {{ productId() }}
`,
})
export class ProductComponent {
 route = inject(ActivatedRoute);
 productId = signal(this.route.snapshot.paramMap.get('id') || '');
}

Ventajas:

  • Eliminamos la necesidad de this.route.params.subscribe().
  • No es necesario limpiar suscripciones en ngOnDestroy.

El Futuro de Angular Signals y la Dirección de Angular: ¿Signals es el futuro de la reactividad en Angular?

Angular Signals es una de las mayores revoluciones en la historia de Angular. Pero, ¿hacia dónde va Angular con esta nueva API?

Aunque RxJS seguirá siendo clave en Angular, es evidente que Signals está tomando un papel central en el manejo del estado. Algunos puntos clave a considerar:

NgRx podría evolucionar hacia Signals
NgRx ha sido la solución estándar para manejar estado global en Angular, pero su complejidad ha sido una barrera de entrada. En el futuro podríamos ver una versión más ligera de NgRx basada en Signals.

Eliminación de Change Detection basado en Zone.js
Angular aún usa Zone.js para detectar cambios en la UI. Signals podría allanar el camino para un Angular sin Zone.js, mejorando el rendimiento de las aplicaciones.

Mayor integración con SSR e Islands Architecture
Con Signals y la hidratación incremental en Angular 19, parece que Angular se está moviendo hacia una arquitectura más eficiente para aplicaciones server-side y con renderizado progresivo.

En resumen

Angular Signals es una de las mejoras más interesantes en Angular en los últimos años. Facilitan la gestión del estado, optimizan el renderizado y reducen la complejidad de la reactividad en los componentes.

Sin embargo, Signals no reemplazan a RxJS, sino que lo complementan. Mientras Signals optimizan el estado de UI, RxJS sigue siendo la mejor opción para manejar flujos de datos asíncronos, eventos y combinaciones de múltiples fuentes de datos.

Si estás en Angular 18 o 19, este es el momento ideal para experimentar con Signals. Y si alguna vez has pasado horas peleando con pipe(), mergeMap() y unsubscribe()… Signals te van a parecer un respiro de aire fresco.

           

Suscríbete a nuestra Newsletter.