paint-brush
A Finite State Machine Helper for Reduxby@maxheiber
5,080 reads
5,080 reads

A Finite State Machine Helper for Redux

by Max HeiberSeptember 3rd, 2016
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

I’ve noticed that <a href="http://redux.js.org/" target="_blank">Redux</a> apps often embed ad-hoc <a href="https://en.wikipedia.org/wiki/Finite-state_machine#Example:_coin-operated_turnstile" target="_blank">finite state machines</a>, with information about the current status spread out throughout <a href="http://redux.js.org/docs/basics/Reducers.html" target="_blank">reducers</a>. I wrote a small helper for working with finite state machines in <a href="https://hackernoon.com/tagged/redux" target="_blank">Redux</a> called <a href="https://www.npmjs.com/package/redux-machine" target="_blank">redux-machine</a>. In this post, I’ll go into:

Companies Mentioned

Mention Thumbnail
Mention Thumbnail

Coin Mentioned

Mention Thumbnail
featured image - A Finite State Machine Helper for Redux
Max Heiber HackerNoon profile picture

I’ve noticed that Redux apps often embed ad-hoc finite state machines, with information about the current status spread out throughout reducers. I wrote a small helper for working with finite state machines in Redux called redux-machine. In this post, I’ll go into:

  • An example of a finite state machine and how to implement it with redux-machine
  • Advantages to using redux-machine

redux-machine Example

This is a very simple example of a state machine for working with data fetching, which will help show how to use redux-machine:

finite state machine for handling API call state in Redux

In words:

  • INIT is the initial status
  • When the status is `INIT` and the action type is `FETCH_USERS`, the machine transitions to `IN_PROGRESS` status.
  • When the status is `IN_PROGRESS` and the action type is `FETCH_USERS_RESPONSE` or `FETCH_USERS_FAIL`, the machine transitions to the `INIT` (initial) status.

I use the term “status” instead of “state” to avoid confusion with “state” in the Redux sense. So INIT and IN_PROGRESS are statuses.

Here’s how you can implement the state machine with redux-machine:

state machine implemented with redux-machine

The special part is the become symbol, which transitions the reducer to a different status. When the status is INIT, fetchUsersReducer acts like initReducer. When the status is IN_PROGRESS, fetchUsersReducer acts like inProgressReducer.

Redux-machine keeps the current status in the store in a non-ad-hoc and explicit way. It stores the current status in the store with the STATUS key. For example, when the status is IN_PROGRESS, the value of “STATUS” is “IN_PROGRESS.”

An app can have arbitrarily many reducers created with redux-machine, and these reducers can be nested. This is helpful because any non-trivial app will have state machines within state machines. For example, if the main flow of the app is:

a simplified main flow for an app

then the statuses in fetchUsers will only be relevant when the main app status is LOGGED_IN.

Advantages of redux-machine

redux-machine makes the current status explicit and keeps your state in the redux store. Keeping all state in the store is useful for:

  • Debugging: the entire state is easily inspectable. redux-machine is also compatible with time-travel debugging.
  • Communicating status to the user. For example, with a loading spinner when the request is active or a “logged in” indicator when the user is logged in.

redux-saga and redux-observable are good at modeling user workflows, but store status outside of the redux store.

Request for Feedback

I haven’t used redux-machine extensively yet, so would welcome feedback and suggestions.