Cuando te adentras en el desarrollo con Angular moderno, uno de los conceptos que más revuelo ha causado en versiones recientes es el uso de signals
. Y no es para menos. Esta nueva forma de gestionar el estado reactivo ha llegado para cambiar la manera en que pensamos nuestras aplicaciones. En este artículo, veremos cómo aplicar un componente con signals en Angular a través de ejemplos prácticos que ayudan a entender realmente cómo funcionan y por qué son tan potentes.
¿Qué es un signal
en Angular?
Un signal
es una función reactiva introducida por Angular para gestionar el estado de una forma más predecible y eficiente. A diferencia de los Observables
, los signals
no necesitan suscriptores ni unsubscribe
manuales. Puedes pensar en ellos como una especie de variable reactiva: cuando su valor cambia, Angular detecta automáticamente el cambio y actualiza la vista.
Esto los convierte en una herramienta excelente para componentes que necesitan reaccionar a cambios rápidos y mantener un código más limpio. Esta capacidad de actualización reactiva sin necesidad de lógica extra es clave para reducir errores y acelerar el desarrollo.
Además, Angular optimiza internamente el rendimiento de estos cambios, lo cual los hace una alternativa ideal en aplicaciones donde el rendimiento importa, como paneles de administración, aplicaciones de tiempo real o experiencias con animaciones interactivas. Puedes revisar la documentación oficial sobre signals en Angular para un entendimiento más profundo.
Ventajas clave de usar signals en Angular
- No necesitas suscripciones: evitas el clásico problema del
unsubscribe
olvidado y los posibles memory leaks. - Más rendimiento: Angular optimiza la detección de cambios gracias al seguimiento interno que usa un modelo de reactividad eficiente.
- Código más legible: declaras el estado y cómo se deriva, sin estructuras complejas ni patrones como Redux.
- Mejor integración con componentes standalone: ideales para apps modernas que no usan módulos y favorecen una estructura más simple.
Otra ventaja adicional es que signals
encajan perfectamente en un enfoque orientado a componentes, donde cada uno gestiona su propio estado sin necesidad de un servicio centralizado o lógica compartida innecesaria.
Si estás empezando con Angular, te recomiendo echarle un vistazo a esta guía para principiantes donde se explica desde cero.
Ejemplo práctico de componente con signals en Angular: contador
Para comenzar a ver signals
en acción, veamos un componente que gestiona un contador. No se trata solo de sumar o restar, sino de mostrar cómo cambia el estado en tiempo real.
✨ El componente CounterPageComponent
explicado
import { Component, signal } from '@angular/core';
@Component({
selector: 'app-counter-page',
standalone: true,
templateUrl: './counter-page.component.html'
})
export class CounterPageComponent {
counter = signal(10);
increaseBy(value: number) {
this.counter.update(current => current + value);
}
resetCounter() {
this.counter.set(0);
}
}
En este ejemplo:
- Declaramos
counter
como unsignal
con valor inicial de10
. increaseBy()
modifica su valor sumando la cantidad indicada.resetCounter()
restablece su valor a cero.
El uso de .update()
es importante porque nos permite acceder al valor actual y modificarlo de forma controlada. Alternativamente, podrías usar .set(counter() + value)
, pero update
es más expresivo y seguro cuando el valor depende del anterior.
🌍 Vista HTML del contador
<div class="text-center">
<h3>Contador actual: {{ counter() }}</h3>
<button (click)="increaseBy(1)">+1</button>
<button (click)="increaseBy(5)">+5</button>
<button (click)="resetCounter()">Reiniciar</button>
</div>
Fíjate cómo usamos counter()
directamente en la plantilla. Esta llamada invoca el getter del signal, actualizando automáticamente la vista si su valor cambia.
Cómo derivar valores con computed
en un componente con signals en Angular
Una vez entiendes el uso de signal
, lo siguiente lógico es computed
. Esta función te permite calcular valores derivados a partir de otros signals. Lo interesante es que Angular solo recalcula cuando los signals base cambian, haciendo el sistema muy eficiente.
Ejemplo práctico: gestión de productos con reactividad
Imaginemos que estamos desarrollando una pequeña app de productos. En lugar de manejar el estado con variables sueltas, usaremos signals y funciones computadas.
📊 Lógica del componente de producto
import { Component, computed, signal } from '@angular/core';
@Component({
selector: 'app-product-page',
standalone: true,
templateUrl: './product-page.component.html',
})
export class ProductPageComponent {
name = signal('Cámara DSLR');
price = signal(499.99);
productDescription = computed(() => {
return `${this.name()} cuesta ${this.price()} €`;
});
discountedPrice = computed(() => (this.price() * 0.9).toFixed(2));
changeProduct() {
this.name.set('Micrófono Profesional');
this.price.set(129.99);
}
applyDiscount() {
this.price.set(this.price() * 0.9);
}
resetProduct() {
this.name.set('Cámara DSLR');
this.price.set(499.99);
}
}
Este componente combina signal
y computed
para manejar información dinámica. Algunas claves importantes:
name
yprice
son signals reactivos.productDescription
depende de ambos y se actualiza automáticamente si cambian.discountedPrice
calcula un valor con descuento sin necesidad de escribir lógica duplicada en la vista.
Esto permite una gran separación entre los datos (signals) y la lógica derivada (computed), facilitando pruebas unitarias y mantenibilidad.
📃 HTML del componente de producto
<div class="container mt-4">
<h2>{{ name() }}</h2>
<p><strong>Precio actual:</strong> {{ price() }} €</p>
<p>{{ productDescription() }}</p>
<p><strong>Precio con descuento:</strong> {{ discountedPrice() }} €</p>
<div class="mt-3">
<button (click)="changeProduct()">Cambiar producto</button>
<button (click)="applyDiscount()">Aplicar descuento</button>
<button (click)="resetProduct()">Reiniciar</button>
</div>
</div>
Aquí, las acciones permiten modificar el estado del producto, que se refleja de inmediato gracias a la reactividad proporcionada por Angular.
Cómo definir rutas usando componentes standalone
Ambos componentes (CounterPageComponent
y ProductPageComponent
) están configurados como componentes standalone. Esto significa que no es necesario registrarlos en un módulo tradicional.
export const routes: Routes = [
{ path: '', component: CounterPageComponent },
{ path: 'producto', component: ProductPageComponent },
];
Esto facilita mucho la escalabilidad de las aplicaciones. Puedes desarrollar y probar cada componente por separado, cargándolos bajo demanda o combinándolos según el flujo de tu aplicación.
Además, usar provideRouter()
y bootstrapApplication()
en lugar de AppModule
es otra forma de mantener el código más limpio y modular.
Aplicaciones reales de un componente con signals en Angular
Los signals
brillan en muchas situaciones del día a día:
- Formularios reactivos: puedes enlazar
signal
con inputs para reaccionar al cambio de forma directa sin[(ngModel)]
niFormControl
. - Dashboards: usar signals para cargar y mostrar KPIs que se actualizan en tiempo real.
- Componentes dinámicos: muestra diferentes bloques de contenido basado en valores derivados sin recurrir a lógica imperativa.
- Renderizado condicional: con
computed
, puedes derivar condiciones y simplificar tus vistas.
El potencial de signals
se multiplica si los usas con effect
, otra función introducida para ejecutar código secundario cuando cambian ciertos valores. Aunque no lo tratamos aquí, es un paso más allá hacia aplicaciones 100% reactivas.
Recomendaciones finales para dominar signals
- Usa
computed
de forma inteligente: evita recalcular cosas en la vista, usa lógica derivada. - No conviertas todo en signal: algunas propiedades estáticas o de un solo uso no lo necesitan.
- Combina
signal
yeffect
para manejar tareas automáticas cuando cambian valores. - Documenta tu lógica: aunque signals son simples, la lógica derivada puede crecer.
Invertir tiempo en comprender estos conceptos al detalle te hará un desarrollador Angular más sólido y preparado para los próximos cambios del framework.
Conclusión sobre el uso de componente con signals en Angular
Trabajar con componente con signals en Angular es una forma moderna, limpia y potente de gestionar el estado. Como has visto, permite construir componentes reactivos sin la complejidad habitual de observables o servicios innecesarios.
Desde un contador hasta un producto con lógica derivada, estos ejemplos te ayudan a entender qué puedes lograr con signal
y computed
. Y esto es solo el principio.
Lo importante ahora es que experimentes por tu cuenta. Juega con los ejemplos, adáptalos a tus propios proyectos y prueba a combinar signals con formularios, animaciones o llamadas HTTP. Verás que la curva de aprendizaje es baja y las ventajas son enormes.
Y si te gustó este enfoque, no te pierdas el artículo donde explicamos paso a paso cómo hacer un CRUD completo con Angular y TypeScript.