"Reactividad en Angular: Migración a Input Signals"
Clase 10 de 36 • Curso de Angular Avanzado
Resumen
La reactividad en Angular ha evolucionado significativamente con la introducción de los Input Signals, una característica que mejora notablemente el rendimiento de las aplicaciones, independientemente de si utilizan server-side rendering o son aplicaciones de formularios, dashboards o backoffice. Esta nueva forma de manejar los datos entre componentes representa un cambio paradigmático en cómo Angular gestiona la reactividad.
¿Qué son los Input Signals y cómo migrar a ellos?
Los Input Signals forman parte del nuevo modelo de reactividad de Angular, diseñado para mejorar el rendimiento de las aplicaciones mediante un enfoque más granular y eficiente. Para entender cómo funcionan, veamos cómo migrar desde el enfoque tradicional.
Anteriormente, definíamos las propiedades de entrada utilizando el decorador @Input()
:
@Input() duration: number;
@Input() message: string;
Con el nuevo modelo de reactividad, la sintaxis cambia a una forma más declarativa:
duration = input.required<number>();
message = input.required<string>();
Este cambio implica:
- Eliminar el decorador
@Input()
- Utilizar la función
input()
que proviene de@angular/core
(en minúscula, no como el decorador) - Especificar si el input es requerido con
.required
- Definir el tipo de dato con genéricos
<number>
,<string>
, etc.
Es importante destacar que aunque la implementación interna cambia, la API externa permanece igual. Es decir, seguimos utilizando los mismos nombres de atributos en las plantillas HTML.
Accediendo a los valores de Input Signals
Una diferencia fundamental es cómo accedemos a los valores. Con los Input Signals, ya no accedemos directamente a la propiedad como una variable normal, sino que debemos ejecutarla como una función:
// Antes
console.log(this.duration); // Imprime el valor directamente
// Ahora
console.log(this.duration()); // Debemos ejecutar el signal para obtener su valor
En las plantillas HTML, también necesitamos ejecutar el signal para obtener su valor:
<p>Duration: {{ duration() }}</p>
¿Cómo detectar cambios en los Input Signals?
Angular mantiene retrocompatibilidad con el método tradicional ngOnChanges
, pero introduce formas más eficientes y declarativas de reaccionar a los cambios.
Método tradicional (aún compatible)
ngOnChanges(changes: SimpleChanges) {
if (changes['duration']) {
console.log('Previous:', changes['duration'].previousValue);
console.log('Current:', changes['duration'].currentValue);
this.doSomething();
}
}
Este enfoque sigue funcionando, pero tiene limitaciones:
- Un solo método para manejar todos los cambios
- Código imperativo para verificar qué propiedad cambió
- Menos legible cuando hay muchos inputs
Nuevo enfoque con effects
constructor() {
effect(() => {
// Se ejecuta cada vez que duration cambia
const value = this.duration();
this.doSomething();
});
effect(() => {
// Se ejecuta cada vez que message cambia
const msg = this.message();
this.doSomethingTwo();
});
}
Las ventajas de este enfoque son:
- Granularidad: cada effect se suscribe específicamente a los signals que utiliza
- Declarativo: el código es más claro y expresa mejor la intención
- Eficiente: solo se ejecuta cuando los signals específicos cambian
Si necesitamos reaccionar a múltiples signals en un mismo effect:
effect(() => {
// Se ejecuta si duration O message cambian
const value = this.duration();
const msg = this.message();
this.doSomething();
});
¿Cómo crear valores derivados a partir de Input Signals?
Una de las características más potentes de los signals es la capacidad de crear valores derivados de forma declarativa y eficiente.
Usando effects (enfoque imperativo)
doubleDuration = signal(0);
constructor() {
effect(() => {
// Actualiza doubleDuration cuando duration cambia
this.doubleDuration.set(this.duration() * 2);
});
}
Usando computed (enfoque declarativo)
doubleDuration = computed(() => this.duration() * 2);
El enfoque con computed
es:
- Más conciso
- Más declarativo
- Más eficiente, ya que Angular optimiza automáticamente cuándo recalcular el valor
Es recomendable usar computed
para transformaciones de datos y reservar effect
para operaciones con efectos secundarios (como llamadas HTTP, manipulación del DOM, etc.).
¿Cuándo utilizar cada enfoque?
- computed: Para transformar datos de forma reactiva sin efectos secundarios
- effect: Para ejecutar código con efectos secundarios cuando cambian los signals
- ngOnChanges: Para mantener compatibilidad con código existente o cuando necesitas comparar valores anteriores y actuales
Los Input Signals representan un avance significativo en el modelo de reactividad de Angular, ofreciendo mejor rendimiento y un código más declarativo. Aunque existe una curva de aprendizaje, los beneficios en términos de rendimiento y mantenibilidad hacen que valga la pena adoptar este nuevo enfoque en tus aplicaciones.
¿Has experimentado con los Input Signals en tus proyectos? ¿Qué otros aspectos de la nueva reactividad de Angular te gustaría explorar? Comparte tus experiencias en los comentarios.