liveBook · Manning

Finite-state machine

As explained in React in Depth

A state machine is a computational model that represents behavior as discrete states and transitions triggered by events or conditions.

A finite-state machine models a flow as named states and the transitions available from each state. A transition may move to another state or leave the current state unchanged while performing an action. This makes complex flows easier to inspect: what can happen next depends on where the flow is now. section 8.7 section 8.7.1

Start with the flow

A signup flow might require credentials, allow an optional details screen, and then require acceptance of terms. A diagram shows both backward navigation and which transitions are available at each step. Data such as a failed-login count can live in the machine’s context rather than in one particular state. section 8.7

Figure 8.18 As the visitor must have a user to proceed on a given website, they can navigate the different states of the diagram, and in the end, they will be given access to the full website. States are boxes, and transitions are arrows. Only the arrows leading out from a given state are allowed transitions from that state. Fully drawn arrows are user-initiated transitions, and dashed arrows are automatic transitions based on various criteria.
figure

The diagram distinguishes states from transitions and shows why an arrow leaving a state defines an available next step. section 8.7

For a React list-and-detail interface, start with `list` and `single` states. Adding an item stays in the list; viewing one moves to detail; removing it returns to the list. Refine the diagram to exclude adding from detail and removing from the list. Separate events for acting on a selected item versus an item identified by ID keep the two views’ behavior explicit. section 8.7.1

An XState implementation separates the flow from its React-facing data layer:

  • Define the initial state, allowed events, targets, and transition actions with `createMachine`; keep the item list and selected ID in its context. section 8.7.2
  • Use `assign` actions to update context. The example keeps these actions in a separate file and performs immutable updates without requiring Immer. section 8.7.2
  • Expose the interpreted machine through a React provider. Hooks select context data with `useSelector` or send events to the service, leaving presentation components behind the data-layer boundary. section 8.0 section 8.7.2
Listing 8.32 src/data/machine.js
import { createMachine } from "xstate";
import {
  doThatThing,
  undoThatThing,
  doThisThing,
  undoThisThing,
  removeThing,
  seeThing,
  seeAllThings,
  addThing,
} from "./actions";
export const machine = createMachine(    #1
  {
    predictableActionArguments: true,
    id: "100-things",    #2
    context: { things: [], currentThing: null },     #3
    initial: "list",    #3
    states: {
      list: {     #4
        on: {   #4
          DO_THAT: { target: "list", actions: "doThatThing" },   #4
          UNDO_THAT: { target: "list", actions: "undoThatThing" },  #4
          ADD: { target: "list", actions: "addThing" },   #4
          SEE: { target: "single", actions: "seeThing" },   #4
        },   #4
      },   #4
      single: {    #4
        on: {
          DO_THIS: { target: "single", actions: "doThisThing" },
          UNDO_THIS: { target: "single", actions: "undoThisThing" },
          REMOVE: { target: "list", actions: "removeThing" },
          SEE_ALL: { target: "list", actions: "seeAllThings" },
        },
      },
    },
  },
  {
    actions: {
      addThing,
      doThatThing,
      undoThatThing,
      doThisThing,
      undoThisThing,
      seeThing,
      seeAllThings,
      removeThing,
    },
  }
);

The machine definition makes the allowed events for each view inspectable in code. section 8.7.2

Persistence needs the whole machine state, including its context: the provider restores that state through `useInterpret` and subscribes to changes to write it to local storage. The extra stored data is a trade-off. Choose a state machine when clarifying a complex flow and its permitted transitions is worth the added modeling; React context with `useReducer`, Redux Toolkit, and Zustand remain alternatives for data management. section 8.7.2 section 8.9

How React in Depth covers it

How deep it goes
Develops a state diagram into an XState machine, actions, React hooks, and persistence; does not examine XState internals.
Examples
Uses a signup flow and a list-and-detail application with distinct view events, context updates, and persisted state.
What it assumes
Assumes familiarity with React hooks and providers while building the state diagram before the XState implementation.
What you can do after
Apply it via XState and @xstate/react to define permitted events, update context, expose data to components, and restore machine state.
How it connects
Connects state diagrams, transition actions, machine context, React providers, selectors, and local storage.

Also explained in

Compare how 9 books explain finite-state machine →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of React in Depth. The section links point to the parts of the book it draws on.