ASAP_A1

Posted on

Getting started with Finite State Machine using X-state.

Introduction

State management in a developer's journey can be hell and bliss, and this depends on the library one chose and how well he grasps the logic behind it right? I must say using a state manager never got better when you can visualize your code logic and decide the kind of beans you're cooking.

In today's session, I'll show us how spectacularly the X-state machine works in practice, and how generously it can make your experience in development worthwhile.

What is a Finite State Machine

The finite state machine can be seen as a mathematical “model” that performs a certain computational activity that assumes an initial state and spins through different[specified] states and back to the normal [accepting state]...
More explanation can be found in my previous article "The finite state machine"

What is X-State

Unlike redux, recoil, Zustand, and a million others, X-State is a library that helps you create finite states, have a visual interpretation, and also execute the logic seamlessly where for instance you will not have to wrap your whole app in a provider, store something or dispatch anything. It's just easy to use and maintain. you can find more explanations here

Getting Started

In this guide we will start by learning how to make a simple dark/light mode, and furtherly a traffic light for our react application all from scratch.
You can find all the working code here on my Github.[drop me a star thanks!]

Setting up

We need to create our app to run this so let's run this;

``````yarn create react-app react-xstate-finite-machine
``````

or

``````npx create react-app react-xstate-finite-machine
``````

Moving forward, we add the `xstate` package to the app;

``````yarn add xstate @xstate/react
``````

Let's run our app `yarn start` or `npm start`[if you are using npm to setup], while our app is building.

Create a file with the name you wish and that is where we will initialize the state like so;

``````import { Machine } from "xstate";

export const switchThemes = Machine({
id: "themes",
initial: "light",
states: {
light: {
on: { SWITCH: "dark" },
},
dark: {
on: { SWITCH: "light" },
},
},
});
``````

Break down

id: just like any state manager it is the name of the name assigned to the state.
initial: that's the [initial]assignment name to the state we want to work with.
states: this is the area we're the state recide.[light&dark]
switch & on: that is what we use to fire the action of switching the themes.

ShowTime

Now it's time to visualize the beans we have been cooking, and `x-state` provides us with a tool called the visualizer which will show us how our state will logically work.

Now you can see that the logic circle began from the initail state of `light` and when a `switch` is invoked it'll change back to `dark`. Nicely yhh?

Back to our code, we would like to see our state in action, so we call our state component to `App.js`, also in order for the state to function fully we have to call the `useMachine` hook from the `x-state` library and we should have something like this.

``````import "./App.css";
import { useMachine } from "@xstate/react";
import { switchThemes } from "./states/darkLightSwitch";

function App() {
const [current, send] = useMachine(switchThemes);

const handleSwitch = () => {
send("SWITCH");
};

return (
<div
className={
current.matches("light") ? "light-theme body" : "dark-theme body"
}
>
<button onClick={handleSwitch}>
{current.matches("light") ? "light" : "dark"}
</button>
<h1>{current.matches("light") ? "Light Turnels" : "Dark Moments"}</h1>
</div>
);
}

export default App;
``````

NB the `light-theme` & `dark-theme` are my CSS classes and they are in their separate folder.

Exciting, isn't it? Now let's get even deeper.

Traffic Lights

Having learned how to add themes to your app why don't we go deeper yeah?
Our traffic lights will assume this looks for now;

We will add a traffic light system into the app and follow prior setup guides for the `dark & light` the theme, we will be having our trafficking[excuse my french] light state like so;

``````import { createMachine } from "xstate";

export const trafficMachine = createMachine({
id: "trafficLights",
initial: "stop",
states: {
stop: {
on: {
NEXT: {
},
},
},
on: {
NEXT: {
target: "go",
},
},
},
go: {
on: {
NEXT: {
target: "stop",
},
},
},
},
});
``````

Yet again visualizer to confirm our act;

Moving forward we will call the state in our application and this time around we will be using our darling `useEffect` to set our timer for the traffic light action, and the entire code should look like this;

``````import "./App.css";
import { useEffect } from "react";
import { useMachine } from "@xstate/react";
import { switchThemes } from "./states/darkLightSwitch";
import { trafficMachine } from "./states/trafficControlState";

function App() {
const [state, send] = useMachine(switchThemes);
const [current, push] = useMachine(trafficMachine);

const handleSwitch = () => {
send("SWITCH");
};

useEffect(() => {
let trigger = () => {
push("NEXT");
};
let timer = setInterval(() => {
trigger();
}, [3000]);
return () => clearInterval(timer);
});

return (
<div
className={
state.matches("light") ? "light-theme body" : "dark-theme body"
}
>
<div className="container">
<button onClick={handleSwitch}>
{state.matches("light") ? "light" : "dark"}
</button>
<h1>{state.matches("light") ? "Light Turnels" : "Dark Moments"}</h1>
</div>
<div>
<ul className="light-container">
<li className={current.matches("stop") && "red"}>
{current.matches("stop") && "STOP"}
</li>
</li>
<li className={current.matches("go") && "green"}>
{current.matches("go") && "GO"}
</li>
</ul>
</div>
</div>
);
}

export default App;
``````

You will notice the call of `useMachine`hook twice, now that's because x-state will not allow you to call more than two actions to the function like our normal `useState` wouldn't.

Check out the app in different modes.