Future of state management in React with XState
Tags: react, javascript, xstate, webdev
Published: 2021-01-05 15:15:17

It is common to see a poll on social media asking for the most common ways to manage state in React. In many cases, the options are limited to **MobX** or **Redux**, **React Context + Hooks**, **Recoil**, but more recently, also **XState**.

With the other tools being well known and primarily accepted (maybe without Recoil, since it's also new), **XState** is still relatively unknown to most developers. 


> **Note:** The purpose of this post is not to compare XState to other state management tools, but rather to tell about the problem it solves and give you a quick introduction, so you can jump and start learning by yourself.

So without further ado, let me tell you more about **XState**. 

## What is XState?

**XState** is a library that brings state machines to **Javascript** and **Typescript** world. State machines are a mathematical concept that has been introduced for describing complex systems. To explain it quickly, imagine a block schema - you have multiple blocks connected with lines and arrows. Those blocks represent states in your application, and lines with arrows represent the flow between those states.

![Block Schema](https://i.stack.imgur.com/aJA2b.png)

If you start from the first block, you can only transition into the block you have a connection with. Therefore you are automatically prevented from transitioning to any block you want. And this is the most significant advantage of using state machines - you can only transition between states that have defined and allowed connections. 

Let's now drop this analogy tho schema and use the proper terminology. 

Every state machine has:
* a **finite number of states** (such as `idle` or `loading`), 
* a **finite number of events** (such as `{ type: 'SEARCH' }` can trigger a transition between states).
* a **list of defined transitions**, which say, "Given some event, go from state idle to pending".

Also, every state machine may have:
* a **context** which is data stored inside the machine,
* a **final state**, after which the machine stops

Okay, so we know what a state machine is. But when seeing a designed schema, it is easy to think about it as a machine. Let's see how one can think of anything like a machine and write it using **XState**. 

## Describing ordinary things in the form of a state machine

Think about water. Just regular water. How does it behave? If we start with the liquid form, it freezes when it's cold, and it vaporizes when we boil it. We can even heat it more and more until it becomes plasma. Let's try to write it down in block schema:

![water machine schema](https://s3.amazonaws.com/media-p.slid.es/uploads/988410/images/7783918/water_machine.png)

When water becomes plasma, we can no longer heat it because it can't change farther. We can only freeze it from there. If we start to freeze plasma, it will become a gas again. The same thing is with ice. If water is in ice form, we can't longer freeze it. We can only heat it.

If you look closely, you will notice that water has no final form. We can always make a transition between its states. Let's see how we could implement it with **XState**.

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

const waterMachine = Machine({
  initial: "liquid",
  states: {
    ice: {
      on: {
        HEAT: {
          target: "liquid",
        },
      },
    },
    liquid: {
      on: {
        HEAT: {
          target: "gas",
        },
        FREEZE: {
          target: "ice",
        },
      },
    },
    gas: {
      on: {
        HEAT: {
          target: "plasma",
        },
        FREEZE: {
          target: "liquid",
        },
      },
    },
    plasma: {
      on: {
        FREEZE: {
          target: "gas",
        },
      },
    },
  },
});
``` 

We need to import a `Machine` creator and pass it into the machine's object. Machine's object has `states` property where we define our states. In each state, we can put the `on` property, which handles events that are defined within.

Event handlers are objects in which we can put `target` property pointing on a different state. This means that when the `HEAT` event in the `ice` state comes, the machine will transition from an `ice` state to a `liquid` state.

This explanation may sound complicated, but it starts to be straightforward if you look into the code. 

## Using XState with React

**XState** is a Javascript library, which means it is framework agnostic. But when it comes to **React**, **XState** gives us hooks for using a defined state machine inside **React** components. All we need to do is to call it, and then we have access to properties like:
* **state** that represents the current state of the machine and its data,
* **send**, a function that sends events to the machine

With that, you can use your machine inside components. You can read its current state (e.g., rendering different components based on state), you can read its context (for displaying data), and you can send events to that machine (make transitions between states).

Just see the usage of our water machine inside the **React** application:

```js
import { useMachine } from '@xstate/react';

// use hooks inside your component
const [state, send] = useMachine(waterMachine);

console.log(current.value)
// 'liquid' 

// send event for making a transition
send("HEAT")

console.log(current.value)
// 'gas' 
```

## Prototyping and debugging with ease

State machines built with **XState** can be visualized with the usage of [XState Viz](https://xstate.js.org/viz/). This fantastic tool allows you to do many things with your machines like debugging, live preview, and interactivity. Just see how we can interact with our water state machine.

![water machine visualized](https://s8.gifyu.com/images/159e650772d49577e.gif)

## Designing complex systems with state machines
When thinking of large web applications, often it comes for us developers to introduce huge and intricate features. Some components are built with dozen or hundreds of child components that also have some logic inside. Coming up with a sound state management system for that can be tricky. Fortunately, state machines fit well for that. 

A state machine can be just like a single block in block schema. Your application can have multiple state machines, which communicate with each other. Also, you can have one main state machine which controls the others and enables that communication.

And all of that logic nested inside multiple state machines can be later visualized with **XState Viz** and be interactive. What a great business value for your PM!

In my opinion, this is the most valuable advantage of state machines over other state management tools - it's not just a library for state management. It is a whole new ecosystem for designing and controlling business logic.

## Going further with XState

If you want to dive deeper into **XState** concepts, I highly recommend visiting the [official XState documentation](https://xstate.js.org/docs/). Documentation is written clearly and is pleasant to read. For those of you who instead prefer video sources over reading documentation, I have prepared an introductory course that is available on **Udemy** - [Introduction to State Machines with XState and React](https://www.udemy.com/course/introduction-to-state-machines-with-xstate-and-react).

Thanks for sticking for that long! If you are interested in the latest tech news, you can follow my account since I plan to post here regularly. I also tweet on a regular basis so that you can follow [My Twitter account](https://twitter.com/SkonecznyJakub) as well!

This post has been originally posted on my [personal blog](https://blog.jskoneczny.pl/post/future-of-state-management-in-react-with-xstate). Please make sure you see it there as well :)

PS. Comment if you have used XState in production!