What about state machines? Can we implement a toggle logic using a state machine? Yes!
In the following lessons we are going to implement the same toggle logic also using a state machine actor.
useReducer
and libraries like redux
contain values inside a store, which is generally a javascript object or primitive value:
type Event = { type: "toggle" };
type Context = boolean; // 👈 Store value (primitive `boolean`)
const initialContext = false;
export const reducer = (context: Context, event: Event): Context => {
if (event.type === "toggle") {
return !context; // 👈 Update store value
}
return context;
};
Instead of working directly with a store, state machines work with states and transitions:
- A machine has a finite number of states
- A machine can be in only one state at a time
- Transitions allow to change the current state
It may sound complex, but don't worry too much for now 💁🏼♂️
We are going to learn more about this new state-based approach as we go through the course.
State machines are often considered more complex, but I aim to show you in this course that it's just a different mental model.
Building blocks of a state machine in XState
A basic state machine in XState is defined using the createMachine
function:
import { createMachine } from "xstate";
const machine = createMachine({});
Inside createMachine
you specify types and configurations for the machine:
Nonetheless, since XState v5 the suggested way to define a machine is using the setup
function instead, and then calling createMachine
from it.
setup
makes the machine more type-safe by definingtypes
to guide its later implementation.
import { setup } from "xstate";
const machine = setup({}).createMachine({});
Inside setup
you specify types and configurations for your machines. No need to understand each option right now, we will learn how to use them in practice when needed.
The main advantage of using setup
is making the machine fully type-safe by defining types
:
If you come from XState v4 keep in mind that XState v5 doesn't need any type generation.
All the types are defined inside
setup
and everything else is inferred!
As mentioned, from setup
we create the concrete machine implementation using createMachine
:
import { setup } from "xstate";
export const machine = setup({}).createMachine({});
Inside createMachine
we define all states and transitions.