Again, using the machine inside a component can be done using useActor
.
This time we access the current context using snapshot.context
. From context
we extract the toggleValue
, and we use it for the checkbox checked
property:
import { useActor } from "@xstate/react";
import { assign, setup } from "xstate";
type Event = { type: "toggle" };
type Context = { toggleValue: boolean };
const initialContext: Context = { toggleValue: false };
const machine = setup({
types: {
events: {} as Event,
context: {} as Context,
},
}).createMachine({
context: initialContext,
initial: "Idle",
states: {
Idle: {
on: {
toggle: {
target: "Idle",
actions: assign(({ context }) => ({
toggleValue: !context.toggleValue,
})),
},
},
},
},
});
export default function MachineContext() {
const [snapshot, send] = useActor(machine);
return (
<input
type="checkbox"
checked={snapshot.context.toggleValue}
onChange={() => send({ type: "toggle" })}
/>
);
}
We learned how to define a state machine with context
and how to update the context using actions
:
- Define the
context
type insidesetup/context
- Define the initial context value inside
createMachine
- Capture the "toggle" event inside the "Idle" state
- Define and execute
actions
We can now compare this context-based machine with the previous state-based machine:
type Event = { type: "toggle" };
type Context = { toggleValue: boolean };
const initialContext: Context = { toggleValue: false };
const machine = setup({
types: {
events: {} as Event,
context: {} as Context,
},
}).createMachine({
context: initialContext,
initial: "Idle",
states: {
Idle: {
on: {
toggle: {
target: "Idle",
actions: assign(({ context }) => ({
toggleValue: !context.toggleValue,
})),
},
},
},
},
});
type Event = { type: "toggle" };
const machine = setup({
types: {
events: {} as Event,
},
}).createMachine({
initial: "Off",
states: {
Off: {
on: {
toggle: { target: "On" },
},
},
On: {
on: {
toggle: { target: "Off" },
},
},
},
});
XState machines combine both context
and states
to allow to model any kind of state. Again, we are going to appreciate the advantages of this state-based approach as we explore more complex use cases in the course.
For now this allowed us to compare useState
, useReducer
, and fromTransition
with state-based and context-based state machines.