Si has estado explorando el desarrollo moderno con Angular, seguro que ya te has topado con los Signals. Son la nueva forma en que Angular maneja el estado de la aplicación de manera hiperreactiva y ultra eficiente. Ya hemos hablado de las señales interactivas, las que podemos cambiarles el valor usando .set() o .update(). Pero, ¿qué pasa cuando necesitas un valor que depende de otra señal? Ahí es donde entra nuestro tema de hoy: computed(). Vamos a ver por qué es tan eficiente y cómo evitar los errores más comunes cuando estás empezando con ello.
[ARQUITECTURA DE SOFTWARE] ESTADO DERIVADO CON ANGULAR: SIGNAL COMPUTED()
¿Qué es un Computed Signal?
Imagina que estás construyendo un carrito de compras. Tienes una señal para el precio del producto y otra para el porcentaje de descuento. El precio final es el resultado de calcular ambas variables.
En lugar de recalcular manualmente el precio final cada vez que cambie el descuento, puedes usar computed signal. Un computed signal es una señal de solo lectura que deriva su valor a partir de otros signals.
TypeScript:
import { signal, computed } from '@angular/core';
// Creamos los signals editables.
precioBase = signal(100); //Precio del producto.
porcentajeDescuento = signal(10); // Descuento 10%.
// Creamos una señal que reaccionará a los signals usando computed()
precioFinal = computed(() => {
const precio = this.precioBase();
const descuento = (precio * this.porcentajeDescuento()) / 100;
return precio - descuento;
});
Aquí el precioFinal depende directamente de los signals precioBase y procentajeDescuento. Cada vez que algun signal cambie, Angular sabrá automáticamente que el valor de precioFinal también debe actualizarse.
Caracteristicas de computed() que debes saber:
precioFinal.set(5); // ERROR DE COMPILACIÓN
- Evaluación perezosa: La función dentro de tu computed() no se ejecutará hasta la primera vez que intentes leer su valor por ejemplo, al mostrarlo en el HTML:
<p><strong>Total a pagar: ${{ precioFinal() }}</strong></p>
- Memorización: Una vez calculado el valor, Angular lo guarda en una memoria caché. Si vuelves a leer precioFinal () cinco veces seguidas, Angular te devolverá el valor guardado de inmediato, todo esto sin volver a hacer la multiplicación.
import { signal, computed } from '@angular/core';
const esUsuarioPremium = signal(true);
const subtotal = signal(100);
const costoEnvio = signal(15); // El envío base es de 15.
const totalConEnvio = computed(() => {
if (esUsuarioPremium()) {
return subtotal(); // No necesita leer el signal costoEnvio.
} else {
// Si el usuario no es premium se lee el signal costoEnvio.
return subtotal() + costoEnvio();
}
});Al entra al primer bloque del if y devuelve el subtotal. Como la señal costoEnvio() nunca se llegó a leer, Angular no la registra como una dependencia.
En el momento en que cambies esUsuarioPremium() a false, Angular volverá a ejecutar la función, leerá costoEnvio() y a partir de ese instante añade el costo de envio como una nueva dependencia.
Buenas Prácticas para no romper tu código.
Es fácil caer en algunas trampas comunes con las Signals cuando recién estas empezando. Grábate estas tres reglas:
- Debe ser una función pura: El único propósito de un computed es calcular y retornar un nuevo valor. Nunca intentes modificar el DOM, cambiar otras variables o alterar otras señales dentro de un computed.
- Prohibido el código asíncrono: Las Signals en Angular son estrictamente síncronas. No metas setTimeout, promesas (Promise) o peticiones HTTP dentro de un computed(). No funcionará como esperas ya que Angular perderá el hilo de qué señales se ejecutaron.
- Usa computed() en lugar de effect() para transformar datos: Si ves que estás usando un effect() para escuchar un cambio en una señal y luego usar un .set() en otra señal. Lo que necesitas es refactorizarlo a un computed()
CONCLUSIÓN
Cada vez que necesites generar datos que dependan directamente de otra información en tu aplicación, tu mejor opción es usar computed(). Te permite crear un estado derivado de forma automática y sin complicaciones.
Una de sus mayores ventajas es la velocidad, ya que guarda los resultados en una memoria caché para evitar cálculos repetidos e innecesarios. Además, te brinda mucha seguridad al programar, porque al ser de solo lectura, tienes la garantía de que nadie podrá modificar su valor por accidente.
Por último, para que todo funcione a la perfección, debes asegurarte de mantener el código dentro de esta función completamente síncrono y libre de efectos secundarios. Tu único objetivo aquí debe ser procesar la información y devolver el nuevo resultado.
No hay comentarios:
Publicar un comentario