Hello XState Part 2: Exploring the XState Viz example
Tags: xstate, statemachines, beginners
Published: 2020-07-13 17:31:16

In my previous post, I discussed why I wanted to learn to use state machines via the XState library.

{%link ekafyi/hello-xstate-learning-state-machines-for-frontend-web-development-5bin %}

XState is [well-documented](https://xstate.js.org/docs/) with ready-to-fork templates for vanilla JS and popular JS frameworks. It also has a cool feature called the **XState Viz (Visualizer)** which, as the name suggests, displays our machine as a diagram with a live sandbox. It’s available in a [web-based](https://xstate.js.org/viz/) version and [as a package](https://github.com/statecharts/xstate-viz) to run locally.

Now let’s open the web-based XState Viz and go over the default example to learn foundational concepts of a machine in XState.

![screenshot showing default example in xstate.js.org/viz](https://dev-to-uploads.s3.amazonaws.com/i/634vuku2u7qmkg2fiorm.png)

On the left we have a diagram illustrating the machine, called `fetch`. On the right we have 3 tabs: **Definition**, **State**, and **Events**. 

## Defining the machine

The **Definition** tab contains… well, the machine’s definition 😬. Here we use the `Machine()` factory function that creates a state machine or statechart. We pass a configuration object there, like so.

```js
const fetchMachine = Machine({
  // Machine identifier
  id: 'fetch',

  // Initial state ...

  // Local context for entire machine ...

  // State definitions ...
});
```

We use the id `fetch` to identify our machine, which is reflected in the top-left diagram label. 

## States

> A state is an abstract representation of a system (such as an application) at a specific point in time.
https://xstate.js.org/docs/guides/states.html

The `fetch` machine has 4 states. In the diagram, a *state* is represented by a *bordered rectangle*. The current active state is indicated by a *blue border*.

![xstate viz screenshot indicating states](https://dev-to-uploads.s3.amazonaws.com/i/czpitg7qldjifqasllc6.png)

The states are:
- `idle` — This is the initial state, as shown by the blue border as well as the start arrow on the left.
- `loading`
- `success`
- `failure`

We define the states in the `states` property and the initial state mode in the `initial` property.

```js
const fetchMachine = Machine({
  id: 'fetch',

  // Initial state
  initial: 'idle',

  // Local context for entire machine ...

  // State definitions
  states: {
    idle: {},
    loading: {},
    success: {},
    failure: {},
  }
});
```

### State types

There are [five types of state nodes](https://xstate.js.org/docs/guides/statenodes.html#state-node-types), which indicate whether a node has child states, initial states, etc. We only see one type here, `final`. As the name suggests, it represents the “terminal” or the last state, indicated by *double border* in the diagram.

```js
const fetchMachine = Machine({
  // other properties truncated
  states: {
    // other states truncated
    success: {
      type: 'final'
    },
  }
});
```

### XState Viz - "State" Tab

Open the **State** tab to see the current active state and context data (more on that below) as a JSON object.

![xstate viz state tab](https://dev-to-uploads.s3.amazonaws.com/i/lmihsi3j6eeyc24gj7or.png)

Click `FETCH` in the diagram. When the active state change to `loading`, the JSON State object gets updated.

## Transitions and Events

> A state transition defines what the next state is, given the current _state_ and _event_. 
https://xstate.js.org/docs/guides/transitions.html

===

> An event is what causes a state machine to transition from its current state to its next state. All state transitions in a state machine are due to these events...
https://xstate.js.org/docs/guides/events.html

To move from one state to another, we need transitions and events. Transitions are defined in the `on` property of each state node, which contains event objects in UPPERCASE. In the diagram, a *transition* is indicated by an *arrow* and an *event* is indicated by a *pill* (box with rounded border and solid background). 

![xstate viz screenshot indicating transitions & events](https://dev-to-uploads.s3.amazonaws.com/i/5sg1cwhybkl6yyu8ut1b.png)

- in `idle` state: 
    - `FETCH` event, transition to `loading` state
- in `loading` state: 
    - `RESOLVE` event, transition to `success` state
    - `REJECT` event, transition to `failure` state
- in `failure` state:
    - `RETRY` event, transition to `loading` state
- No transition in `success` state as it has a `final` type.

```js
const fetchMachine = Machine({
  // other properties truncated
  states: {
    idle: {
      on: {
        FETCH: 'loading'
      }
    },
    loading: {
      on: {
        RESOLVE: 'success',
        REJECT: 'failure'
      }
    },
    // success truncated
    // more on failure state below
  }
});
```

We configure our machine states in accordance to our app logic, that it’s  not possible to go from `idle` state to `success` or `failure`. This is what I like about state management solutions—be it state machines library like this one or libraries like Redux and Vuex—as opposed to, say, the [useState hook](https://reactjs.org/docs/hooks-state.html). It provides better assurance regarding our states behavior and minimizes nested conditionals in the UI.

### Heads up: Shorthands ✋🏼

You can write the transition as an object or using a shorthand string; they do the same thing.

```js
idle: {
  on: {
    // state transition - shorthand
    FETCH: 'loading'

    // OR

    // state transition - object
    FETCH: {
      target: 'loading'
    }
  }
}
```
### XState Viz - "Events" Tab

Open the **Events** tab to see the list of events that have been run.

![xstate viz events tab](https://dev-to-uploads.s3.amazonaws.com/i/qtpxkqgrp7dsqvt72tnp.png)

## Context and Actions

> Actions are fire-and-forget "side effects". For a machine to be useful in a real-world application, side effects need to occur to make things happen in the real world, such as rendering to a screen.
https://xstate.js.org/docs/guides/actions.html

===

> [S]tate that represents quantitative data (e.g., arbitrary strings, numbers, objects, etc.) that can be potentially infinite is represented as extended state [...]. In XState, extended state is known as context.
https://xstate.js.org/docs/guides/context.html

Often, we need to store and update data associated with this machine other than the state name. We use context to do this. Context data are updated with the `assign()` action in a state’s transition.

In the diagram, the assign action and the associated context is _printed under_ a transition event.

![xstate viz screenshot indicating context and assign action under an event](https://dev-to-uploads.s3.amazonaws.com/i/tvlnjdtxbw07u5uubprl.png)

Our fetch machine has one context object, `retries`, set at the initial value of `0`. It is incremented by 1 whenever `RETRY` transition event runs from the `failure` state to the `loading` state.

Setting up the `retries` context object and initial value:

```js
const fetchMachine = Machine({
  // other properties truncated
  context: {
    retries: 0
  }
});
```

Updating `retries`  in the `RETRY` transition:

```js
failure: {
  on: {
    RETRY: {
      target: 'loading', // state transition with object
      actions: assign({
        retries: (context, event) => context.retries + 1
      })
    }
  }
}
```

## Conclusion

The [XState Viz](https://xstate.js.org/viz/) machine example helps us understand the most basic usage of concepts like **states**, **transitions**, **events**, **actions**, and **context**. The diagram helps us visualize the interaction between those concepts. At this point, we don’t have to deal with importing packages or complicated syntax/API beyond basic vanilla JS.

Of course, in order to grok the concepts beyond this example, we need to read the documentation, follow tutorials, and practice. To be honest, I still need to re-read the docs to get a better understanding of some parts that just go _whoosh_ over my head so far.

In the next post,  I’m going to _create my own machine_ from scratch in XState Viz. Stay tuned and thank you for reading!

---

## Bonus Track

{% twitter 1271019974442835971 %}

--- 

## References

XState official documentation
* [States](https://xstate.js.org/docs/guides/states.html)
* [State Node Types](https://xstate.js.org/docs/guides/statenodes.html#state-node-types)
* [Transitions](https://xstate.js.org/docs/guides/transitions.html)
* [Events ](https://xstate.js.org/docs/guides/events.html)
* [Actions ](https://xstate.js.org/docs/guides/actions.html)
* [Context](https://xstate.js.org/docs/guides/context.html)