El patrón sobrevive a la librería y a la plataforma
Cierre del nivel: cuatro puertos del mismo patrón —vanilla, NgRx, Pinia y Nanostores— permiten separar por comparación lo invariante de lo circunstancial. Esta lección aísla las cuatro garantías que aparecen en todos ellos, muestra qué varía siempre y por qué varía —la capa de enlace, la técnica de detección de cambios, el grano de la ceremonia—, propone un procedimiento de cuatro preguntas para reconocer la arquitectura de estado de cualquier stack desconocido en una tarde, y termina con lo único que este track pretendía dejarte: un criterio que no caduca cuando caduque el catálogo.
Hemos visto el mismo patrón cuatro veces en cuatro disfraces: un contador de DOM sin framework, un stream de RxJS en Angular, un store con proxies en Vue y un átomo de trescientos bytes compartido entre islas de tres frameworks distintos. Cuatro puertos son suficientes para hacer lo que una sola implementación nunca permite: separar por comparación lo que aparece siempre de lo que cambia en cada caso. Lo que aparece siempre es el patrón; lo que cambia es su factura en un entorno concreto. Esta lección aísla lo primero, explica lo segundo y te deja un procedimiento para reconocer ambas cosas en un stack que no conoces, porque esa capacidad —y no una lista de librerías de 2026— es lo único de este track que seguirá valiendo dentro de diez años.
- Aislar las cuatro garantías invariantes que aparecen en todos los puertos del patrón.
- Identificar qué varía siempre entre implementaciones y por qué razón técnica varía.
- Aplicar cuatro preguntas para mapear la arquitectura de estado de un stack desconocido.
- Formular un criterio de elección que no dependa del catálogo de librerías vigente.
Las cuatro invariantes
Pon los cuatro puertos en columna y tacha todo lo que no aparezca en los cuatro. Lo que queda no son cuatro librerías ni cuatro APIs: son cuatro garantías, y ninguna de ellas menciona un framework.
Una verdad con dueño
Cada dato vive en un sitio y solo uno. Store, átomo o módulo: el nombre cambia, la unicidad no. Copiarlo es el bug original.
Una frontera de escritura
Hay un conjunto estrecho y nombrado de formas de cambiar el estado. Acciones, mutaciones o funciones exportadas: nadie escribe por fuera.
Lo impuro, aparte
Peticiones, temporizadores y aleatoriedad viven en una capa propia. Thunks, effects o acciones asíncronas, siempre fuera de la decisión pura.
Lectura derivada y observada
La vista no posee estado: lo selecciona, lo deriva de forma memoizada y se entera cuando cambia. Nunca lo copia ni lo sincroniza a mano.
Un modo rápido de comprobar que son de verdad invariantes es intentar quitar una y observar qué reaparece. Sin dueño único, el mismo dato vive en dos sitios y se desincroniza: es el bug fundacional de 2014. Sin frontera de escritura, un cambio inexplicable obliga a buscar por toda la base de código quién pudo hacerlo. Sin aislamiento de lo impuro, la lógica deja de ser reproducible y las pruebas necesitan red. Sin lectura derivada y observada, alguien copia el estado a una variable local y empieza a sincronizarlo a mano. Cada garantía que retiras devuelve exactamente el problema que la motivó, en cualquier framework y en cualquier década.
Estas cuatro garantías son el patrón. Todo lo demás que has aprendido en el track —los objetos de acción con tipo, los reducers puros, la inmutabilidad, combineReducers, createSlice, el viaje en el tiempo— son técnicas para conseguirlas en un entorno determinado, y por eso cambian de un puerto a otro sin que las garantías cambien. Redux consigue la frontera de escritura obligando a despachar acciones; Pinia la consigue exportando solo acciones desde el store; Nanostores la consigue exportando funciones y no el set desnudo. Tres técnicas, una garantía.
flowchart TD PAT[cuatro garantias invariantes] --> V[vanilla con subscribe] PAT --> N[ngrx con rxjs] PAT --> P[pinia con proxies] PAT --> NS[nanostores entre islas] V --> ENL[lo que cambia es la capa de enlace] N --> ENL P --> ENL NS --> ENL style PAT fill:#f38ba8,color:#11111b style ENL fill:#f9e2af,color:#11111b
Lo que cambia, y por qué cambia
Si las garantías son fijas, resulta útil catalogar las tres variables que se mueven, porque son exactamente las tres preguntas que te harás en cada stack nuevo. La primera es la capa de enlace: cómo se entera la vista. React necesita useSyncExternalStore para evitar el desgarro; Angular usa observables o señales; Vue rastrea dependencias con proxies; el DOM plano llama a una función. La segunda es la técnica de detección de cambios: comparar referencias exige inmutabilidad, observar escrituras permite mutabilidad. La tercera es el grano de la ceremonia: cuánto hay que declarar para obtener trazabilidad, que depende de si el entorno puede observar el cambio o hay que anunciárselo.
La tabla resume el nivel entero y hace visible que la columna de la izquierda no cambia nunca y las de la derecha siempre.
| Puerto | Cómo se entera la vista | Detección de cambios | Ceremonia |
|---|---|---|---|
| Vanilla | subscribe y repintar a mano |
manual, la decides tú | mínima |
| NgRx | observable o señal inyectada | inmutabilidad con Immer | alta, la del ecosistema |
| Pinia | reactividad con proxies | observación directa | baja |
| Nanostores | adaptador por framework | reemplazo del valor del átomo | mínima |
Ninguna fila es mejor que otra en abstracto: cada una es la respuesta correcta al entorno que la produjo. Leer la tabla como un ranking es el error que este nivel intenta desactivar.
Merece la pena estirar la tesis más allá del navegador, porque ahí se ve mejor su alcance. Bloc en Flutter separa eventos, estados y una capa de efectos con exactamente las mismas cuatro garantías; la arquitectura de composición de Swift define una reducción pura, un almacén de efectos y una vista suscrita; los sistemas de eventos de los backends distribuidos llevan medio siglo escribiendo un registro inmutable de hechos del que se deriva el estado actual. No es que estos ecosistemas se hayan copiado entre sí: es que el problema —muchos actores modificando un estado compartido y alguien que necesita entender por qué cambió— tiene un número muy pequeño de soluciones buenas, y todas se parecen.
La relación entre las tres variables no es caprichosa, y verla ordenada evita muchas discusiones estériles. La técnica de detección de cambios que ofrece el entorno determina cuánta ceremonia hace falta: donde el runtime no observa mutaciones hay que anunciarlas, y anunciarlas es la ceremonia. La ceremonia, a su vez, condiciona cuánta trazabilidad obtienes gratis, porque un cambio anunciado es un cambio registrable. Así que cuando alguien compara dos gestores de estado por número de líneas está midiendo el último eslabón de una cadena cuyo primer eslabón es una propiedad del framework, no una decisión de la librería.
Hay un cuarto eje, menos técnico y más organizativo, que también varía: cuánta trazabilidad exige el dominio. Un editor colaborativo, una herramienta financiera o cualquier sistema con deshacer profundo necesita que cada cambio sea un valor serializable y reproducible, y entonces la ceremonia de las acciones nombradas deja de ser peaje y pasa a ser el requisito. Una tienda con un carrito y un tema no necesita nada de eso. El mismo patrón admite ambas facturas, y elegir la equivocada —en cualquiera de las dos direcciones— es el error de diseño más común de esta área.
Cómo aterrizar en un stack desconocido
De todo lo anterior sale un procedimiento concreto, y es probablemente lo más útil que te llevarás del nivel. Cuando entres en un ecosistema que no conoces —Svelte con sus stores, SolidJS con sus señales, Flutter con Bloc o Riverpod, SwiftUI con su modelo observable, o lo que exista cuando leas esto—, no busques el nombre de la librería de estado. Haz estas cuatro preguntas, que son las cuatro garantías en forma interrogativa.
// Un mapa de arquitectura de estado cabe en cuatro campos, en cualquier stack.
type MapaDeEstado = {
verdad: string // donde vive el dato y quien es su dueno unico
escritura: string // que mecanismo estrecho puede cambiarlo
efectos: string // donde se aisla lo impuro: red, tiempo, aleatoriedad
lectura: string // como deriva y como se entera la vista
}
const ngrx: MapaDeEstado = {
verdad: 'store unico inyectado',
escritura: 'dispatch de acciones hacia reducers puros',
efectos: 'createEffect sobre el stream de acciones',
lectura: 'selectores memoizados como observable o signal',
}
El mismo mapa relleno para los otros tres puertos del nivel muestra hasta qué punto las respuestas se parecen pese a lo distinto del vocabulario. En Pinia: la verdad es un store por dominio, la escritura son sus acciones, los efectos viven dentro de esas acciones asíncronas y la lectura son getters observados por proxies. En Nanostores: la verdad es un módulo con átomos, la escritura son funciones exportadas, los efectos viven en esas funciones y la lectura son computed más un adaptador por framework. En vanilla: la verdad es el store, la escritura es dispatch, los efectos van en middleware y la lectura es subscribe más un repintado. Cuatro ecosistemas, cuatro veces la misma estructura.
Rellena esos cuatro campos para el stack nuevo y tendrás su arquitectura de estado entera, sin haber leído un tutorial. Si alguno queda vacío, has encontrado el punto débil de ese ecosistema o el punto ciego de tu lectura, y en ambos casos sabes exactamente qué investigar a continuación. Es el mismo ejercicio que hicimos con NgRx, con Pinia y con Nanostores, y funcionó las tres veces porque las preguntas no dependen de la respuesta.
Quién es el dueño
Dónde vive cada dato y quién lo posee. Si la respuesta son dos sitios, ya tienes el primer bug localizado.
Quién puede escribir
Qué mecanismo estrecho y nombrado aplica los cambios. Si la respuesta es cualquiera, no hay arquitectura que revisar.
Dónde vive lo impuro
En qué capa concreta se aíslan red, tiempo y azar. Si están repartidos por la vista, las pruebas te lo dirán pronto.
Cómo se entera la vista
Qué mecanismo notifica y con qué grano. Es la única de las cuatro cuya respuesta cambia de verdad al cruzar de stack.
Estas preguntas también sirven hacia dentro, y ahí es donde más valen: aplicadas a tu propio proyecto suelen revelar que la arquitectura escrita en el documento de diseño y la que el código practica de verdad no coinciden. Es habitual descubrir un dato con dos dueños que nadie había advertido, o una escritura que esquiva la frontera desde un archivo antiguo. Ninguno de esos hallazgos requiere cambiar de librería para arreglarse.
Cuando el campo de escritura contiene la palabra cualquiera, no tienes una frontera: tienes un objeto global compartido con nombre elegante, y los bugs de origen desconocido llegarán solos. Cuando el campo de lectura contiene la palabra copiar —copiamos el dato del servidor al store, copiamos el store al estado local—, tienes dos fuentes de verdad para el mismo dato y una desincronización garantizada, que es literalmente el problema que Flux nació para resolver en 2014. Ambas señales aparecen en stacks modernos con la misma frecuencia que en los antiguos, porque no son fallos de las herramientas sino del mapa mental de quien las usa.
El criterio que no caduca
Queda una última pieza: cómo elegir cuando llegue la próxima ola. La respuesta que este track ha ido construyendo no es una recomendación sino un criterio de dos pasos. Primero, clasifica el estado por su naturaleza, como hicimos en el Nivel 7: qué es servidor, qué es cliente compartido, qué es derivado, qué es local. Segundo, para cada clase elige la herramienta cuya factura de ceremonia coincida con la trazabilidad que ese dominio exige, teniendo en cuenta qué te regala ya el entorno. Ningún paso menciona un nombre propio, y por eso ninguno caduca.
Clasifica antes de elegir
La primera pregunta ante cualquier dato no es dónde lo guardo, sino de qué clase es. La herramienta se deduce de la clase.
Paga la ceremonia que uses
Cada línea de ritual compra una garantía. Si tu dominio no la necesita, es peaje; si la necesita, es la inversión más barata que harás.
Las signals que hoy se extienden por todos los ecosistemas son la prueba en tiempo real de este criterio: cambian la técnica de detección de cambios y, con ella, el grano de ceremonia necesario, exactamente como los proxies de Vue lo cambiaron hace años. Si las lees como el fin de los gestores de estado, te sorprenderá que sigan apareciendo stores encima de ellas; si las lees como una capa de enlace mejor, entenderás por qué NgRx expone selectSignal y por qué el patrón sigue ahí debajo, intacto.
Este track empezó con un problema de mensajes duplicados en un chat de 2014 y termina con átomos compartidos entre islas de frameworks distintos, y entre esos dos extremos hay una continuidad que conviene nombrar con precisión antes de cerrar: lo que se transmitió de un extremo al otro no fue ninguna librería —Flux original está muerto, Redux dejó de ser el default, Vuex fue reemplazado por su sucesor y Nanostores será reemplazado por algo más pequeño— sino un conjunto de garantías sobre cómo debe comportarse el estado compartido para que un sistema siga siendo comprensible cuando crece, y esas garantías han sobrevivido intactas a tres generaciones de herramientas, a cuatro frameworks incompatibles entre sí y a un cambio completo de arquitectura de renderizado. La consecuencia práctica es que hay dos formas radicalmente distintas de haber leído estos dieciocho niveles: como un curso de Redux con apéndices, en cuyo caso lo aprendido caducará con la próxima ola y volverás a sentirte principiante en cuanto cambies de stack; o como un curso sobre el problema del estado compartido en el que Redux fue el ejemplo mejor documentado, en cuyo caso lo aprendido se aplicará a cualquier herramienta que venga, incluidas las que aún no existen, porque el problema que resuelven no ha cambiado desde que existen las interfaces de usuario y no va a cambiar ahora. La diferencia entre ambas lecturas no está en el material sino en qué nivel de abstracción decidiste retener, y esa decisión la tomas tú al cerrar la última lección. Si te llevas cuatro preguntas —quién es el dueño, quién puede escribir, dónde vive lo impuro, cómo se entera la vista— eres portable a cualquier stack y cualquier plataforma, y los nombres de moda de cada año te resultarán, correctamente, un detalle de implementación. Si te llevas una lista de APIs, has memorizado un catálogo que ya está caducando mientras lo lees.
- Elige un ecosistema que nunca hayas usado: Svelte, SolidJS, Flutter, SwiftUI o el que prefieras, cuanto más ajeno mejor.
- Sin leer tutoriales de su gestor de estado, dedica treinta minutos a rellenar los cuatro campos del mapa: verdad, escritura, efectos y lectura.
- Busca ahora su solución idiomática y contrasta tu mapa con ella. Anota qué acertaste, qué te faltó y por qué.
- Localiza cuál de las tres variables —capa de enlace, detección de cambios, grano de la ceremonia— explica la mayor diferencia con Redux en ese stack.
- Escribe el mismo mapa para el proyecto en el que trabajas hoy y busca honestamente las dos señales de alarma: la escritura abierta a cualquiera y el dato copiado.
- Redacta, en menos de diez líneas, la guía que le darías a alguien que empieza mañana en tu proyecto para decidir dónde poner cualquier pieza de estado nueva. Si esa guía menciona una librería antes que una garantía, reescríbela.