State, Events, and Transitions
In this first lesson, we'll get familiar with three key concepts important to state machines: state, events, and transitions. Let's start by defining them:
-
State: The status or condition of a machine at a given time.
-
Event: A signal that tells a machine something has happened (can trigger state changes, though not every event will). For example, a button being clicked or a file being finished loading.
-
Transition: A rule that defines when and how a machine can change from one state to another in response to an event. It ensures you can only move between states in predefined ways.
A state machine is finite, meaning it has definable limits. Therefore, all possible states can be and are predefined, and they can only be in one of those states at a time.
For example, a light bulb can be in an "On" or "Off" state. It cannot be in both states at the same time, nor can it be in a "Half On" state. That's assuming its not a dimmable light bulb, of course.
If it were a dimmable light bulb, it could arguably have a "Half On" state if the dimmer were set to exactly 50%, couldn't it? What if it were set to 49.9893937234% or any other possible value between 0 and 100 though? That's an example of "infinite" or "non-finite" state, a concept we'll explore later.
A Light Switch Machine
Here's a simple state machine that models a light switch. It transitions between "Off" and "On" when a “switch” event is sent. The white arrow indicates the initial state of the machine.
In XState, a state machine is defined using a JSON-like object.
- The setup function is specifically for making TypeScript happy, it defines the event type. We'll be working with that a lot, but if you're not using TypeScript, you can ignore it.
- The initial property defines the initial state of the machine.
- The states property defines the possible states of the machine.
- The on property defines the type of event and the target state to transition to.
- The target property defines the state to transition to when the event is received
To use this machine our app, we pass it to the useMachine hook provided by the @xstate/react package.
- The useMachine hook returns the current state and a function to send events to the machine.
- The send function sends the "switch" event to the machine.
- The type property defines the event type that triggers the transition.
- The matches method checks if the machine is in a specific state.
You can see an example of this in the code editor to you right. Click the button in the preview panel to toggle betweeen states. Notice how the button's text changes from "On" to "Off" and back again, reflecting the current state of the machine.
Exercise
- In machine.ts, change the event type from "switch" to "toggle" in the machine definition.
- In App.tsx, update the event type in the send method to match the new event type.
- Test the changes by clicking the button in the preview panel.
- In machine.ts, change the the name of the first state from "Off" to "Inactive" and the second state from "On" to "Active".
- In App.tsx, update the button's text to reflect the new state names.
- Test the changes by clicking the button in the preview panel.
Summary
In this lesson, we learned how to create a simple state machine using XState and integrate it into a React app. Next, we'll learn how to model more complex state machines with compound states and parallel states.