Angular 21 de Cero a Experto / Signals a fondo
Signals: el valor que avisa cuando cambia
Aquí empieza el corazón de Angular 21. Una signal es un contenedor de un valor que, cuando
cambia, AVISA a todo lo que dependa de él para que se actualice. Es el equivalente de
useState de React, pero de grano más fino y sin re-renderizar componentes enteros. Hoy
entiendes qué es una señal, cómo se lee y escribe… y construyes tu propia versión desde cero
para ver que no hay magia, solo una idea muy elegante.
El marcador que grita el cambio
Crear, leer y cambiar una señal
import { Component, signal } from '@angular/core';
@Component({
selector: 'app-contador',
template: `
<p>Gastos registrados: {{ cuenta() }}</p> <!-- se LEE con () -->
<button (click)="agregar()">Agregar</button>
`,
})
export class ContadorComponent {
cuenta = signal(0); // crear una señal con valor inicial 0
agregar() {
this.cuenta.set(this.cuenta() + 1); // set: reemplazar el valor
// o: this.cuenta.update(n => n + 1); // update: derivar del anterior
}
}Tres operaciones, nada más:
- Leer:
cuenta()—la llamas como función—. En el template{{ cuenta() }}, en la clasethis.cuenta(). Ese paréntesis es la clave: al leerla, Angular anota "quien está leyendo ahora depende de esta señal". set(valor): reemplaza el valor por uno nuevo.update(fn): calcula el nuevo valor a partir del actual —como la forma funcionalsetCuenta(n => n + 1)de React—.
Cuando llamas set o update, la señal notifica a todo lo que la leyó (el template, un
computed, un effect) y solo ESO se actualiza.
El puente desde React (y la diferencia clave)
Si vienes de React, esto se parece muchísimo a useState:
// React: // Angular:
const [cuenta, setCuenta] = cuenta = signal(0);
useState(0);
cuenta; // leer cuenta(); // leer (con paréntesis)
setCuenta(5); // cambiar cuenta.set(5); // cambiar
setCuenta(n => n+1); // derivar cuenta.update(n => n + 1);Construye tu propia señal
¿Magia? Para nada. Una señal es un valor guardado en un closure, con una función para leerlo y otra para cambiarlo. Aquí está la versión mínima —el mismo principio que usa Angular por dentro— corriendo en vivo. Léela y ejecútala:
¿Ves lo que pasó? Al leer la señal dentro de un observador, ésta lo GUARDA como dependiente.
Al escribir, RECORRE sus dependientes y los vuelve a ejecutar. Eso es todo el sistema
reactivo en 15 líneas. Angular añade rendimiento, pereza y detección de ciclos, pero la idea
es exactamente ésta: leer registra la dependencia, escribir notifica. Lo profundizarás en
las próximas lecciones con computed y effect —y al final del módulo construirás la
versión completa—.
¿Por qué una señal se lee llamándola como función, `cuenta()`?
Mini-reto
En el playground, amplía tu señal: 1) crea una señal saldo que empiece en 100000;
2) engancha un observador que imprima `Saldo: ${saldo()}`; 3) haz un par de update
que resten gastos (s => s - 4500) y observa cómo el mensaje se reimprime solo con cada
cambio. Confirma que NO tuviste que llamar al console.log manualmente tras cada cambio: la
señal avisó.
Qué sigue
Tienes el ladrillo básico. Pero el poder real llega al DERIVAR: "el total es la suma de los
gastos", "el saldo es el presupuesto menos el total". La próxima lección es computed: una
señal calculada a partir de otras que se recalcula sola —y también la construirás desde
cero—.