JavaScript de Cero a Experto / Patrones y observables
El store observable: un valor que avisa
El bus transmite sucesos que vuelan; pero el corazón de una app es su ESTADO: el total, el usuario, el tema — valores que están ahí y cambian. Hoy construyes el patrón que los gobierna: el store observable — un valor con suscriptores. Son 15 líneas, y son el abuelo directo de los signals de Angular, de Zustand y del estado de React.
El marcador del estadio
Las 15 líneas
Tres decisiones de diseño para masticar: el set IGNORA cambios que no
cambian nada (nuevo === valor) — sin eso, cada asignación redundante
dispararía avisos en cascada; la suscripción avisa DE INMEDIATO con el
valor actual — así el recién llegado no espera al próximo cambio para
pintarse (fíjate: la pantalla imprimió "total: 0" al suscribirse); y el
valor vive encerrado en la mochila — la ÚNICA puerta de escritura es
set, tu garantía de que ningún rincón de la app cambia el estado sin
que los demás se enteren.
Derivados: valores que se calculan solos
¿Y si un valor DEPENDE de otro? Se suscribe y se recalcula — el getter del módulo 11, en versión reactiva:
function derivar(estadoFuente, transformar) {
const derivado = crearEstado(transformar(estadoFuente.get()));
// cuando la fuente cambie, el derivado se recalcula y AVISA a los suyos
estadoFuente.suscribir((v) => derivado.set(transformar(v)));
return derivado;
}
const total = crearEstado(0);
const enCOP = derivar(total, (t) => t.toLocaleString("es-CO"));
enCOP.suscribir((texto) => console.log("formateado:", texto));
total.set(48000); // "formateado: 48.000" — en cadena, soloCambias total y enCOP se actualiza y avisa a los suyos — una cadena
reactiva. Y aquí la confesión que hace clic con todo: esto ES un
signal. Cuando en Angular escribas total = signal(0) y
enCOP = computed(...), o en React veas el estado re-renderizar
componentes, estarás usando ESTE patrón con optimizaciones industriales
(detección automática de dependencias, agrupación de avisos, integración
con el render). El mecanismo — un valor, un solo escritor, suscriptores
avisados — ya es tuyo.
Nota honesta: nuestro store guarda un VALOR simple y compara con === —
suficiente aquí. Con objetos y arrays, el === compara referencias… y ahí
la inmutabilidad del módulo 12 deja de ser filosofía y se vuelve
REQUISITO: solo produciendo un objeto nuevo en cada cambio el store puede
detectar que algo cambió. Por eso React exige inmutabilidad: su store
compara referencias, exactamente como el tuyo.
Un compañero exporta el objeto de estado crudo y en un archivo lejano alguien hace estado.valor = 99999 directo (imagina que fuera posible). Los suscriptores no se enteran y la pantalla queda vieja. ¿Cuál es la lección de diseño?
Mini-reto
Sube tu store de nivel: 1) haz que set acepte también una FUNCIÓN
(total.set((v) => v + 18000)) — si recibe función, la aplica al valor
actual (inspecciona con typeof); 2) crea gastos = crearEstado([]) y
súmale gastos con set-función + spread inmutable (¡módulo 12!); 3) deriva
cantidad de gastos con tu derivar y comprueba la cadena completa:
un push inmutable → dos avisos en cascada. Acabas de escribir la mitad de
Zustand.
Qué sigue
Eventos que vuelan (bus), valores que avisan (store)… falta gobernar los PROCESOS: cosas que pasan por etapas — una petición que va de "cargando" a "éxito" o "error", un pedido que se paga y se envía. Cuando las etapas y sus caminos válidos se declaran explícitos, los bugs de "¿cómo llegó a este estado?" se extinguen. Próxima lección: la máquina de estados.