State. We all love it, yet we all hate it. Without state, our most useful web applications would still be immovable pixels on a screen, but on the other side, those pesky bugs related to state management wouldn't exist either.
Thanks to really smart computer scientists and years of web developers learning the hard way how to effectively manage state in applications, we finally have a good solution to describe and manage UI state reliably in the form of statecharts and FSMs.
Statecharts are a formalism for modeling stateful, reactive systems. This is useful for declaratively describing the behavior of your application, from the individual components to the overall application logic. - XState
Explained simply ...
A statechart is a simple way to describe all of the states that a system can exist in or transition to. A finite-state machine is a type of system whose states are limited and predictable.
You're probably thinking, "cool, good to know, but how do I actually implement them in my web apps?". To use FSMs in web applications, XState is the way to go.
Let's talk about buttons. A simple UI button has four basic states: up/default/unpressed, hovered, pressed, and disabled.
The disabled state will be defined by the component's parent. The disabled state is isolated from all other states in the statechart, as no internal transition should disable the button, and the button shouldn't be capable of enabling itself on its own.
Below, you'll see two statechart visualizations of the previously described button. One picture shows the enabled path and the other shows the disabled path.
As you can see, once in the disabled state, the machine has no way to get out of it unless the machine is recreated with the disabled prop being set to false.
For rendering the button's UI, I'll be using React Native Web and React Hooks. A hook I'll make good use of is
useMachine, which takes a configured XState machine and handles updating the component with new states created by sending transition actions to the hook.
To create a button that changes its state appropriately, I used the
onMouseLeave event props to send their respective transition to the useMachine hook.
Since React function components are called/recreated every time it is re-rendered, I can calculate the styles based on the current machine state exposed by the useMachine hook with ease.
There aren't any real steps or further explanation needed to understand how the code works, so I'll just show it below:
To play with the code and experience a live demo of this fantastic state machine-powered button, check out the CodeSandbox here.
I hope you learned a bit about how to think about UI state with statecharts and can think of ways to integrate state machines in your React apps.