@ivanbtrujillo

XState

XState es una librería para crear, interpretar y ejecutar state machines, escrita en Typescript.

ɛkssteɪt

State machine

Una state machine o maquina de estado define el comportamiento de un sistema que sólo puede estar en un estado para un momento dado.  

¿Qué es una statechart?

Es un formalismo para modelar mediante diagramas una state machine

Off

On

Interruptor

Posibles estados: ON / OFF

Transiciones:  ON -> OFF / OFF -> ON

Si está apagada y se alterna el interruptor, pasará a estar encendida

Si está encendida y se alterna el interruptor, pasará a estar apagada

 

Historias

Creando una state machine

npm install xstate
import { createMachine, interpret } from 'xstate';

const lightMachine = createMachine({
  id: 'light',                     // identificador único
  initial: 'off',                  // estado inicial
  states: {                        // estados soportados (off, on)
    off: { on: { TOGGLE: 'on' } }, // transiciones permitidas
    on: { on: { TOGGLE: 'off' } }
  }
});

¿Cómo se usa?

/* 
 * Obtenemos un servicio como resultado de interpretar 
 * la máquina que hemos creado y la arrancamos
 */
const lightService = interpret(lightMachine).start();

Interpretamos la máquina y la arrancamos, obteniendo un servicio.

console.log(lightService.state.value); // off

Podemos ver el estado de nuestra máquina

Podemos enviar eventos

lightService.send('TOGGLE'); // on

Visualizador

Herramienta para visualizar nuestra state machine en una statechart e interactuar con ella 

Nuestra lightMachine

Extensión para VSCode

El contexto

El contexto es un estado extendido, y es una forma de representar los datos que acompañan a nuestro estado.

 

import { createMachine, interpret } from 'xstate';

const lightMachine = createMachine({
  id: 'light',                     
  initial: 'off',                  
  context: {
  	color: 'yellow'
  },
  states: {                        
    off: { on: { TOGGLE: 'on' } }, 
    on: { on: { TOGGLE: 'off' } }
  }
});

¿Cómo lo modificamos?

Utilizando acciones, que son funciones que se disparan cuando una transición ocurre. Disponemos de un tipo de acción especial llamada assign.

 

import { ..., assign } from 'xstate';
...
  states: {
    off: {
      on: {
        TOGGLE: {
          target: "on", // Estado objetivo
          actions: [
            assign({
              color: (context, event) => "red"   // Asignamos el contexto
            })
          ],
        },
      },
    },
    ...
  },
...

Contexto dinámico

O pasarlo como parámetro al enviar nuestra acción

... 
 assign({
   color: (context, event) => context.color === 'yellow' ? 'red' : 'yellow';
 }),
...
lightService.send("TOGGLE", {
    color: "purple"
});

...
  assign({
   color: (context, event) => event.color
 }),
...

Podemos calcular el nuevo contexto en base al valor actual

 

¿Qué más podemos hacer?

  • Ejecutar acciones sólo si se cumple una condición (guarded transitions)
     
  • Ejecutar acciones cuándo entramos o salimos de una transición ( entry / exit actions)
     
  • Invocar servicios
     
  • Crear estados jerárquicos
     
  • Invocar transiciones retrasadas (delayed transitions)
     
  • Mucho más

¿Por qué elegir XState?

  • Estados predecibles
     
  • No se pueden introducir estados no-válidos
     
  • Visualmente reproducibles (trabajo en equipo)
     
  • Pensar en los estados y sus transiciones nos fuerza a pensar en la lógica antes de escribir código.
     
  • Buena documentación
     
  • La lógica puede discutirse con personas que no-desarrolladoras.
     
  • Agnóstica

¿Dónde aprender?

El futuro

Demo

@ivanbtrujillo

Gracias

XState - Expero Night

By Iván BTrujillo

XState - Expero Night

  • 1,909