Fetching Image Data
Learn about creating a simple image-fetching state machine in XState, handling different states, using the invoke property, and exposing fetched data to a parent machine.
Fetching data isn’t always the strong suit of state management libraries. After all, it’s not their basic responsibility. In the case of XState, however, fetching comes very naturally, as every Promise can be modeled as a state machine. At a high level, we need to kick off a function that will be in a default loading state. We’ll wait for something to happen with it—either resolve or reject—and go to the appropriate resolved or rejected states.
Image-fetching machine
Here’s how our image-fetching machine is shaping up:
// src/machines/fetchImageMachine.jsimport { createMachine, assign } from "xstate";// XState machine definition for fetching imagesexport const fetchImagesMachine = createMachine({id: "fetchImages",// Initial stateinitial: "loading",// Context to hold machine-specific datacontext: {retries: 0, // Number of retry attemptsimages: [], // Array to store fetched images},// States of the machinestates: {loading: {on: {RESOLVE: "success", // Transition to 'success' state on successful image fetchREJECT: "failure", // Transition to 'failure' state on unsuccessful image fetch},},success: {type: "final", // Final state indicating successful image fetch},failure: {on: {RETRY: {target: "loading", // Retry fetching images by transitioning back to the 'loading' stateactions: assign({retries: (context, event) => context.retries + 1, // Increment the number of retry attempts}),},},},},});// Don't change the code above, add comments as requested.
What we can see here is a very simple machine prepared to describe the process of fetching data from an external source. We have three states:
The initial state of
loading
on line 20.The
success
state on line 26.The
failure
states on line 29.
We can see two actions in the loading
...