Contenido del curso
Machines 101
Machines 102
Cierre
Contexto en XState: leer y actualizar datos
Resumen
El contexto en XState funciona como una memoria extendida de la máquina de estados, donde guardas datos que cambian a lo largo del flujo. Si vienes construyendo una máquina y necesitas almacenar información como un país seleccionado o una lista de pasajeros, aquí aprendes a inicializar, leer y actualizar ese contexto con ejemplos reales.
Esto te sirve si ya entendiste cómo declarar estados y transiciones, pero quieres que tu máquina recuerde información entre pasos.
¿Qué es el contexto en una máquina de estados?
En XState, el contexto es la propiedad donde guardas datos persistentes mientras la máquina se mueve entre estados. Piensa en él como un objeto compartido que cualquier estado puede leer y modificar a través de acciones.
En un flujo de reserva de vuelos, por ejemplo, el contexto guarda dos cosas concretas: un array de pasajeros y un string con el país seleccionado [0:48].
¿Para qué sirve el contexto en XState? Para almacenar datos que sobreviven entre transiciones, como inputs del usuario, selecciones o listas que se van construyendo paso a paso.
¿Cómo se setea el contexto inicial?
Dentro del objeto principal de la máquina, declaras la propiedad context con los valores iniciales que necesitas. Es la base sobre la que vas a trabajar.
js context: { passengers: [], selectedCountry: '' }
Acá defines un array vacío para los pasajeros y un string vacío para el país. Cuando arranca la máquina, ese es el estado de tus datos [1:20].
¿Cómo leer el contexto desde la vista?
Para inspeccionar el contexto, te vas al base layout y simplemente imprimes state.value junto con state.context. Con eso ya tienes visibilidad de qué hay guardado en cualquier momento del flujo [1:42].
Esto resulta clave mientras debuggeas: ves cómo evoluciona el objeto a medida que disparas eventos.
¿Cómo se actualiza el contexto con assign?
La función assign es la herramienta que XState te da para modificar el contexto. La importas desde la misma librería, al lado de createMachine, y la usas dentro de las actions de una transición.
La lógica es simple: cuando ocurre un evento, en lugar de cambiar de estado a secas, ejecutas una action con assign que recibe el contexto actual y el evento, y retorna el nuevo valor.
¿Cómo guardar el país seleccionado al continuar?
En la vista de search, cuando el usuario da clic en continuar, le pasas como segundo parámetro al send un objeto con la información que quieres guardar:
js send('CONTINUE', { selectedCountry: flight })
Del lado de la máquina, en la transición del estado search, defines el target al siguiente estado y agregas un actions con assign:
js actions: assign({ selectedCountry: (context, event) => event.selectedCountry })
Acá le dices a assign que cambie la propiedad selectedCountry del contexto usando lo que viene en el evento [3:10]. Al refrescar y seleccionar un país como Venezuela, ves cómo el contexto se actualiza al dar continuar.
¿Qué hace assign en XState? Es la función que actualiza el contexto de la máquina dentro de una acción, recibiendo el contexto actual y el evento para calcular el nuevo valor.
¿Cómo agregar elementos a un array dentro del contexto?
Para mantener una lista de pasajeros, creas un evento ADD en el estado de pasajeros cuyo target es sí mismo. Es decir, sale del estado y vuelve a entrar, pero ese ciclo te permite ejecutar la action que actualiza el contexto [4:38].
js on: { ADD: { target: 'passengers', actions: assign((context, event) => { context.passengers.push(event.newPassenger) }) } }
Nota la diferencia con el ejemplo anterior: aquí declaras assign con una función general en lugar de especificar la propiedad. Ambas formas funcionan, y vale la pena conocerlas para no perderte cuando las veas en código ajeno.
¿Cómo conectar el formulario con el evento ADD?
En la vista de pasajeros, en el submit del formulario, envías el evento junto con el nuevo nombre:
js send('ADD', { newPassenger: value })
Al probarlo, escribes Camilo Lamilla, das enter y aparece en el array. Agregas Carlos Gómez y ahora el contexto guarda ambos nombres [6:15]. Cada submit dispara la transición que ejecuta assign y actualiza la lista.
¿Cuándo conviene usar cada forma de declarar assign?
Tienes dos estilos disponibles y conviene reconocerlos:
- Assign con objeto de propiedades: especificas qué campo del contexto cambias y con qué función. Útil cuando actualizas pocas propiedades de forma puntual.
- Assign con función general: recibes el contexto y el evento, y modificas lo que necesites dentro. Útil cuando haces operaciones más complejas como un
pusha un array. - Assign declarado inline vs. fuera: puedes ponerlo directamente en la transición o sacarlo a la sección de actions declaradas para reutilizarlo.
Las dos formas hacen lo mismo al final, pero te dan flexibilidad según el caso.
Reto: reiniciar el contexto y mostrar el listado
Con lo que ya manejas (inicializar, leer y actualizar contexto), tienes dos retos para practicar:
- Cuando el usuario dé cancelar y vuelva al estado welcome, reinicia el contexto a sus valores iniciales: array vacío y string vacío.
- En la vista de pasajeros, muestra el listado de los pasajeros agregados encima del input, leyendo directamente del contexto.
¿Cómo resolverías el primer reto? Cuéntame en los comentarios qué enfoque tomarías para el assign que reinicia ambos valores a la vez.