{"id":367,"date":"2021-02-02T23:08:02","date_gmt":"2021-02-02T23:08:02","guid":{"rendered":"http:\/\/rainforestqa.com\/selecting-a-finite-state-machine-library-for-react\/"},"modified":"2023-02-14T01:38:35","modified_gmt":"2023-02-14T01:38:35","slug":"selecting-a-finite-state-machine-library-for-react","status":"publish","type":"post","link":"https:\/\/www.rainforestqa.com\/blog\/selecting-a-finite-state-machine-library-for-react","title":{"rendered":"Selecting a finite state machine library for React"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">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\u2019m also going to share why I believe our codebase could benefit from using it. Let\u2019s start with that.<\/p>\n\n\n\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_84 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.rainforestqa.com\/blog\/selecting-a-finite-state-machine-library-for-react\/#The_Rainforest_automation_editor_needs_a_refactor\" >The Rainforest automation editor needs a refactor<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.rainforestqa.com\/blog\/selecting-a-finite-state-machine-library-for-react\/#So_is_there_anything_else_apart_from_XState\" >So is there anything else apart from XState?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.rainforestqa.com\/blog\/selecting-a-finite-state-machine-library-for-react\/#XState_vs_Robot\" >XState vs Robot<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.rainforestqa.com\/blog\/selecting-a-finite-state-machine-library-for-react\/#Summary\" >Summary<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.rainforestqa.com\/blog\/selecting-a-finite-state-machine-library-for-react\/#Related_articles_videos\" >Related articles &amp; videos<\/a><\/li><\/ul><\/nav><\/div>\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"The_Rainforest_automation_editor_needs_a_refactor\"><\/span>The Rainforest automation editor needs a refactor<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">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.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/uploads-ssl.webflow.com\/60da68c37e5767dfb65004c0\/61f1c759df626c6a3fc5930e_rfa_editor_initialization.gif\" alt=\"\"\/><figcaption class=\"wp-element-caption\">The Rainforest no-code test editor initialization<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">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 <em>boolean salad<\/em> 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\u2019m talking about:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>const isDeleteDisabled =\n  hasPendingUpdate ||\n  isBlockSelectionEmpty ||\n  isReplayingActions ||\n  isReplayingInitialNavigate ||\n  isActionSelectionIndeterminate;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">So what is a better alternative to the <em>boolean salad<\/em> we\u2019re 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\u2019s 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.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As mentioned before I haven\u2019t 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 <a href=\"https:\/\/github.com\/davidkpiano\/xstate\" target=\"_blank\" rel=\"noopener\">XState<\/a> 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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"So_is_there_anything_else_apart_from_XState\"><\/span>So is there anything else apart from XState?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">There are a few alternatives out there. Searching the web for <em>React state machine<\/em> mostly returns <strong>XState<\/strong> and sometimes <strong>Robot<\/strong> related pages, but switching the search terms to a more generic <em>javascript state machine<\/em> helped with unraveling a few more.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s summarize a few basic stats about the libraries I\u2019ve found. The data was collected on 26th January 2021.<\/p>\n\n\n\n<table><thead>\n<tr>\n<th>Name<\/th>\n<th>Github star count<\/th>\n<th>Last updated<\/th>\n<th>Bundle size*<\/th>\n<th>Comes with React friendly integrations<\/th>\n<\/tr>\n<\/thead><tbody>\n<tr>\n<td><a href=\"https:\/\/github.com\/davidkpiano\/xstate\" rel=\"noopener\" target=\"_blank\">xstate<\/a><\/td>\n<td>14.5k<\/td>\n<td>hours ago<\/td>\n<td>16.7 kB<\/td>\n<td>Yes<br><a href=\"https:\/\/xstate.js.org\/docs\/recipes\/react.html#hooks\" rel=\"noopener\" target=\"_blank\">xstate-react<\/a> <code>useMachine<\/code> hook<\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/github.com\/matthewp\/robot\" rel=\"noopener\" target=\"_blank\">robot<\/a><\/td>\n<td>1.2k<\/td>\n<td>hours ago<\/td>\n<td>1.2 kB<\/td>\n<td>Yes<br><a href=\"https:\/\/thisrobot.life\/integrations\/react-robot.html\" rel=\"noopener\" target=\"_blank\">react-robot<\/a> <code>useMachine<\/code> hook<\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/github.com\/cerebral\/overmind\" rel=\"noopener\" target=\"_blank\">overmind<\/a><\/td>\n<td>1.2k<\/td>\n<td>hours ago<\/td>\n<td>10.4 kB<\/td>\n<td>Yes<br><a href=\"https:\/\/github.com\/cerebral\/overmind\/tree\/next\/packages\/node_modules\/overmind-react\" rel=\"noopener\" target=\"_blank\">overmind-react<\/a> provides both hooks and HOCs<\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/github.com\/krasimir\/stent\" rel=\"noopener\" target=\"_blank\">stent<\/a><\/td>\n<td>675<\/td>\n<td>5 months ago<\/td>\n<td>3.3 kB<\/td>\n<td>Yes<br><a href=\"https:\/\/github.com\/krasimir\/stent\/blob\/master\/docs\/react-integration.md\" rel=\"noopener\" target=\"_blank\">part of bundle<\/a> <code>connect<\/code> HOC<\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/github.com\/jakesgordon\/javascript-state-machine\" rel=\"noopener\" target=\"_blank\">javascript-state-machine<\/a><\/td>\n<td>7.6k<\/td>\n<td>3 years ago<\/td>\n<td>2.6 kB<\/td>\n<td>No<\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/github.com\/ifandelse\/machina.js\" rel=\"noopener\" target=\"_blank\">machina.js<\/a><\/td>\n<td>1.9k<\/td>\n<td>2 years ago<\/td>\n<td>27.1 kB<\/td>\n<td>No<\/td>\n<\/tr>\n<\/tbody><\/table>\n\n\n\n<p class=\"wp-block-paragraph\"><em>* Minified + gzipped size from <\/em><a href=\"https:\/\/bundlephobia.com\/\" target=\"_blank\" rel=\"noopener\"><em>bundlephobia.com<\/em><\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>javascript-state-machine<\/strong> and <strong>machina.js<\/strong> aren\u2019t actively updated anymore and they don\u2019t come with React integrations out of the box which disqualifies them from further investigation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>stent<\/strong> doesn\u2019t 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\u2019t 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.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>overmind<\/strong> looks interesting but it is providing much more than just state machines. From briefly scanning through the docs, I would say it is a <strong>redux<\/strong> alternative with built in support for state machines and a state chart addon. We\u2019re using <strong>redux<\/strong> in our application and we currently don\u2019t plan to replace it which is why it doesn\u2019t seem like the right choice, it would be overkill considering we only need a state machine abstraction.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That leaves us with <strong>xstate<\/strong> and <strong>robot<\/strong>. Let\u2019s look at these two in a bit more detail.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"XState_vs_Robot\"><\/span>XState vs Robot<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">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:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/xstate.js.org\/docs\/about\/goals.html#api-goals\" target=\"_blank\" rel=\"noopener\">XState API goals<\/a> (XState docs)<\/li>\n\n\n\n<li><a href=\"https:\/\/thisrobot.life\/guides\/comparison-with-xstate.html\" target=\"_blank\" rel=\"noopener\">Comparison between XState and Robot<\/a> (Robot docs)<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Both Robot and XState share these similarities:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Extended state (context) makes it possible to keep non-state values within the machine.<\/li>\n\n\n\n<li>Both can <a href=\"https:\/\/www.w3.org\/TR\/scxml\/#invoke\" target=\"_blank\" rel=\"noopener\">invoke<\/a> external functions as well as other state machines to perform subtasks.<\/li>\n\n\n\n<li>Both support <a href=\"https:\/\/thisrobot.life\/api\/guard.html\" target=\"_blank\" rel=\"noopener\">guards<\/a> which allow the addition of custom logic to prevent state transitions from occurring.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">XState comes with more functionality built in:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Serializing state machines into JSON format easily.<\/li>\n\n\n\n<li>Supports the actor model as an alternative to invoking machines.<\/li>\n\n\n\n<li>Comes with a <a href=\"https:\/\/xstate.js.org\/viz\/\" target=\"_blank\" rel=\"noopener\">visualizer tool<\/a> that gives a visual representation of the state machine.<\/li>\n\n\n\n<li>Conforms to the <a href=\"https:\/\/www.w3.org\/TR\/scxml\/\" target=\"_blank\" rel=\"noopener\">SCXML<\/a> specification. This standard defines a XML schema for describing state machines, and supporting it means it\u2019s theoretically possible to import and export the XML for a XState state machine so it can be used in multiple languages.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">So what are we going to use for the Rainforest automation editor refactor? The XState visualizer is attractive, but I don\u2019t see the need for the other advanced features that XState provides which is why I\u2019m 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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Summary\"><\/span>Summary<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">State machines can help with improving the readability and maintainability of UI state management logic. We\u2019re looking into using them in the most complex parts of our application but that doesn\u2019t mean they can\u2019t be useful for simpler components. There are many articles describing their advantages, I\u2019ve linked a few below in case you\u2019re 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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Related_articles_videos\"><\/span>Related articles &amp; videos<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u200d<a href=\"https:\/\/statecharts.github.io\/\" target=\"_blank\" rel=\"noopener\">Erik Mogensen &#8211; Welcome to the world of Statecharts<\/a><a href=\"https:\/\/www.youtube.com\/watch?v=VU1NKX6Qkxc\" target=\"_blank\" rel=\"noopener\">\u200d<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=VU1NKX6Qkxc\" target=\"_blank\" rel=\"noopener\">David Khourshid &#8211; Infinitely Better UIs with Finite Automata<\/a> (XState)<a href=\"https:\/\/daveceddia.com\/react-confirmation-modal-state-machine\/\" target=\"_blank\" rel=\"noopener\">\u200d<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/daveceddia.com\/react-confirmation-modal-state-machine\/\" target=\"_blank\" rel=\"noopener\">Dave Ceddia &#8211; Build A Confirmation Modal in React with State Machines<\/a> (Robot)<a href=\"https:\/\/jonbellah.com\/articles\/intro-state-machines\/\" target=\"_blank\" rel=\"noopener\">\u200d<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/jonbellah.com\/articles\/intro-state-machines\/\" target=\"_blank\" rel=\"noopener\">Jon Bellah &#8211; A Complete Introduction to State Machines in JavaScript<\/a> (XState)<a href=\"https:\/\/www.smashingmagazine.com\/2018\/01\/rise-state-machines\/\" target=\"_blank\" rel=\"noopener\">\u200d<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.smashingmagazine.com\/2018\/01\/rise-state-machines\/\" target=\"_blank\" rel=\"noopener\">Krasimir Tsonev &#8211; The Rise Of The State Machines<\/a> (Stent)<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\u200d<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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\u2019m also going to share why I believe our codebase could benefit from [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","inline_featured_image":false,"footnotes":""},"categories":[6],"tags":[],"class_list":["post-367","post","type-post","status-publish","format-standard","hentry","category-engineering"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.rainforestqa.com\/blog\/wp-json\/wp\/v2\/posts\/367","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rainforestqa.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rainforestqa.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rainforestqa.com\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rainforestqa.com\/blog\/wp-json\/wp\/v2\/comments?post=367"}],"version-history":[{"count":3,"href":"https:\/\/www.rainforestqa.com\/blog\/wp-json\/wp\/v2\/posts\/367\/revisions"}],"predecessor-version":[{"id":876,"href":"https:\/\/www.rainforestqa.com\/blog\/wp-json\/wp\/v2\/posts\/367\/revisions\/876"}],"wp:attachment":[{"href":"https:\/\/www.rainforestqa.com\/blog\/wp-json\/wp\/v2\/media?parent=367"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rainforestqa.com\/blog\/wp-json\/wp\/v2\/categories?post=367"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rainforestqa.com\/blog\/wp-json\/wp\/v2\/tags?post=367"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}