This article is going to look at different libraries providing finite state machine abstractions that can be used in React applications. I have used state machines on the backend in the past but I have never used one in a React application. I’m also going to share why I believe our codebase could benefit from using it. Let’s start with that.
One of the most complex parts of our frontend codebase is the test editor for the Rainforest no-code testing product. The related code has been through a lot of changes in the past 2 years and its complexity increased as time passed. Apart from other data structures, we store a lot of boolean flags in the editor state. We use them to dispatch side effects and to inform the user about what is currently happening in the editor.
The amount of boolean flags increased with the overall complexity of the editor and it became hard to work with them because making a decision on what to do next or what to render in the UI often requires combining many of them. The resulting boolean salad became hard to read and reason about. It became obvious it was time to take a different approach if we wanted to keep our sanity. Here is one really bad example of what I’m talking about:
So what is a better alternative to the boolean salad we’re currently maintaining? I believe state machines are a great candidate for describing all possible states of the editor and transitions between them. These states and transitions are currently somewhat scattered throughout the codebase and getting an overall picture of what happens when and what are all the possible combinations requires a lot of jumping around. Making a mental map of all the possibilities is therefore difficult and that also means it’s difficult to onboard new developers. The ability to quickly analyze the application states and transitions between them can also be beneficial while collaborating with project managers, designers, customer support represantitives or anyone else interested in the product functionality. A diagram of the state machine can be a great addition to feature documentation.
As mentioned before I haven’t used a state machine library in React yet so I wanted to look around to find out what options are available. The only one I was aware of before starting a deeper search was XState from David Khourshid. It seems to be quite popular and successful but I like to look around for alternatives before committing to the most hyped option.
Let’s summarize a few basic stats about the libraries I’ve found. The data was collected on 26th January 2021.
* Minified + gzipped size from bundlephobia.com
stent doesn’t seem to have enough community traction and it only provides an HOC for connecting the state machines to React components. The HOC only integration isn’t really much of an issue, but I slightly prefer using hooks where possible. Less active development and popularity are my main reasons for not diving deeper.
overmind looks interesting but it is providing much more than just state machines. From briefly scanning through the docs, I would say it is a redux alternative with built in support for state machines and a state chart addon. We’re using redux in our application and we currently don’t plan to replace it which is why it doesn’t seem like the right choice, it would be overkill considering we only need a state machine abstraction.
That leaves us with xstate and robot. Let’s look at these two in a bit more detail.
The first obvious difference between these two is the bundle size, Robot is much smaller at 1.2 kB minified and gzipped compared to XState which takes up 16.7 kB. Keeping the size minimal is an intentional constraint of Robot. I think that these two pages from the library authors sum up their goals nicely:
Both Robot and XState share these similarities:
XState comes with more functionality built in:
So what are we going to use for the Rainforest automation editor refactor? The XState visualizer is attractive, but I don’t see the need for the other advanced features that XState provides which is why I’m currently leaning towards using Robot. I like the functional based API that allows for easy composition and I also like that its bundle size is so lightweight.
State machines can help with improving the readability and maintainability of UI state management logic. We’re looking into using them in the most complex parts of our application but that doesn’t mean they can’t be useful for simpler components. There are many articles describing their advantages, I’ve linked a few below in case you’re interested in getting a deeper understanding of why and when state machines are a good choice. I hope you found the article helpful in choosing the right library for your use case.