State machines and state management

::info Update June 2023: added a section outlining what my current approach is. :::

State management is one of the most complicated, and opinionated topics in modern and JavaScript-focused front-end development. But at its core, it is not that complicated. We just make it complicated. In this article I will try to demystify state and state management for you, and challenge your mental models around them.

What is state?

Is state some weird data storage? Is it the data from a database? No. State is nothing more than a JavaScript value that lives within in scope. It can be a boolean, a string, but is in most cases a (complex) object. But it remains a value. In most cases, it is even an object living on the same level as the window object. It has become a global value in the JavaScript environment, the browser window. From our code (e.g. UI components), we can use this value to determine what to show or what interactions to allow. In complex applications there are a few different types of state we can have. But remember, they are nothing more than values.

State management

So what about state management? For many, state management feels like a black box. What is happening within Redux? Why does it feel so complicated? I look at it this way: State management is nothing more than patterns to make it "easier" for us to change state.

State management is nothing more than patterns to make it "easier" for us to change state

In modern front-end there are several different patterns that are popular to use these days.

What to use?

Different types of state require different solutions. There is no single state management solution that works best for all. The framework or library that you are using limits or helps you as well with this decision. React offers a big ecosystem and a lot of choices. Like a lot. But Svelte on the other hand has a tremendous implementation right out of the gate.

My own approach is a mixture of different patterns for different purposes. For remote state I would use service workers or create/use a library around 'state-while-revalidate'. This s a great example where state machines In the background these are powered by state machines to avoid unwanted caching side-effects.

For things like application state or meta state, it highly depends on the complexity of the challenge. If it is something simple, a small reactive store like a signal or a flat proxy suffices. However, it the challenge becomes more complex I will choice one of two routes:

  1. If there are many actual 'states' I would model everything in a reactive state machine.
  2. If the goal is data manipulation in many ways, I would go for a reactive proxy that allows me to define a state API. These are functions defining how I can interact with the state (e.g. the chifferobe package).

The common theme in my approach is reactivity. Even an "SWR-like" library is reactive. The thing is, in front-end development we always want something to change when our state changes.

Wrapping up

Now you should have a better understanding of some fundamentals of state management. Knowing the different types of state and how to manage state is the start. With proper state management, you can get a long way in complex web applications. But it is the start. There are many (more) ways to manage data that are important in client-side applications. When you master state, go dive into persistent storage or caching.