Contenido del curso
Machines 101
Machines 102
Cierre
Servicios en XState para requests HTTP
Resumen
Los servicios en XState son funciones que invocas desde una máquina de estados para ejecutar tareas asíncronas como hacer un request a una API, comunicar máquinas padre e hijo o escuchar eventos del teclado. Aprendes a integrarlos para que tu aplicación obtenga datos reales sin perder el control del flujo de estados.
¿Qué tipos de servicios existen en XState?
Antes de invocar cualquier función, conviene saber qué herramientas tienes disponibles. XState clasifica los servicios en cuatro grupos según cómo se comunican con la máquina.
- Servicios de promesas: ejecutan una promesa, como un
fetch, y devuelven el resultado. Son ideales para requests HTTP. - Servicios de callbacks: usan un callback para comunicar la máquina padre con la hija de forma directa.
- Servicios observables: emiten un flujo de eventos, útil para reemplazar listeners tradicionales como
onmousedowno eventos de teclado. - Servicios de invocación de máquinas: permiten que una máquina padre invoque múltiples hijas y se comuniquen con
sendysendParent.
¿Qué hace el atributo invoke en XState? Es la propiedad que declara qué servicio ejecuta un estado, con un
idpara identificarlo y unsrcque apunta a la función a llamar.
¿Cómo invocar una promesa para hacer un request?
En el proyecto la meta es traer un listado de países desde una API y mostrarlos en un select. Primero se crea una carpeta utils con un archivo api.js que contiene fetchCountries, una función que hace un fetch a la URL y retorna la respuesta.
Dentro de la máquina, en el estado de loading del nodo fillCountries, se reemplazan las acciones por un invoke. Este recibe un id (getCountries) y un src apuntando a fetchCountries.
¿Cómo manejar el éxito del request con onDone?
La propiedad onDone se ejecuta cuando la promesa resuelve correctamente. Allí defines:
- Un target que apunta al estado de éxito, en este caso
success. - Un action que usa
assignpara guardar la respuesta dentro del contexto.
La asignación queda como countries: (context, event) => event.data. En el contexto inicial agregas countries: [] y error: "" para tener valores por defecto.
¿Cómo manejar errores con onError?
La propiedad onError cubre el caso en que el request falle. El target apunta a failure y la acción asigna al campo error el string "falló el request". Adicionalmente, un evento retry permite volver al estado loading y reintentar el proceso completo.
¿Qué pasa si el request falla? La máquina transiciona a
failure, guarda el mensaje en el contexto y queda lista para reintentar mediante el eventoretry.
¿Cómo conectar el contexto con el componente?
Una vez que el array de países vive en el contexto de la máquina, el componente search deja de usar datos quemados. Desde stepsLayout se pasa el state como prop al search, y dentro del componente se asigna options = state.context.countries.
La API devuelve cada país con un atributo name.common, así que el map de las opciones se actualiza para usar option.name.common como etiqueta visible. Al refrescar el navegador y darle a comenzar, el select se llena con los países reales del endpoint.
[01:42] aparece el detalle clave: un error tipográfico al escribir event como ewent impide que el contexto reciba los datos. Corregir la w por la e deja el flujo funcionando.
¿Cómo agregar una transición por tiempo con after?
El último ajuste introduce una transición temporizada en el estado tickets. La propiedad after permite que una máquina espere un delay antes de cambiar de estado.
La configuración queda así:
- Dentro de tickets, declarar el bloque
after. - Definir un delay de 5000 milisegundos.
- Apuntar el
targetal estadoinitial. - Ejecutar el action
cleanContextpara resetear los datos.
Después de cinco segundos en la pantalla del ticket, la aplicación regresa sola al inicio con el contexto limpio. También se ajusta el componente nav para que el botón cancelar solo aparezca cuando el estado sea distinto de initial y de tickets.
¿Qué servicio implementarías primero en tu propio proyecto: una promesa, un observable o la invocación de otra máquina? Comenta tu caso.