Frontend Quick Tips #16 How to Escape From Boolean Trap With State Machines
Those may be some patterns explained in JS code on real-life examples or some techniques for better code.
Problem
In a typical scenario when an application needs to connect to external resources/services (e.g. by API) to gather some data, our component’s state (or state container) has a bunch of boolean flags with a lot of conditional checking, where the initial state is:
{
isPending: true,
isFulfilled: false,
isRejected: false
}
and the next state (e.g. when request is successfully fulfilled):
{
isPending: false,
isFulfilled: true,
isRejected: false
}
Solution
Use a state machine
Quoting Wikipedia, a state machine (or FSM) is:
"It is an abstract machine that can be in exactly one of a finite number of states at any given time. The FSM can change from one state to another in response to some inputs; the change from one state to another is called a transition".
I have prepared a super simple and minimal state machine, you can get it here:
https://gist.github.com/serrg/e794b30b8dc3ebee29b096770f075b1c
Now your component’s state (or state container) could be like:
{
state: {}
}
Where state
is your state machine with declared transitions and status:
const machine: Machine = createMachine<State>({
init: "idle",
transitions: [
{ name: "start", from: "idle", to: "pending" },
{ name: "success", from: "pending", to: "fulfilled" },
{ name: "failure", from: "pending", to: "rejected" }
],
actions: {
start: () => {
console.log("action started");
},
success: () => {
console.log("action successed");
},
failure: () => {
console.log("action failed");
}
}
});
machine.state; // state: idle
machine.action("start"); // action started, state: pending
machine.action("success"); // action successed, state: fulfilled
machine.action("failure"); // action failed, state: rejected
By using a machine.state
property rather than a boolean flag indicator we enable our users to know exactly what the state is at any given point in time.
Our flow now looks like:
There are more complex and more powerful state machines, you can find libraries for any framework or language here: https://github.com/leonardomso/awesome-fsm. When it comes to frontend, the most popular library is XState.