The state of the state: React state management in 2018
Joshua Nelson ✨
Posted on June 15, 2018
There's always been a myriad of ways to manage state in React. Redux has always been a popular choice, but with React 16, and recently released libraries, there are now even more options. What are these options, and why would you use any of these over any others?
I've gone through some popular choices for managing state in React, and created very simple todo apps to demonstrate their usage. I've tried to keep things as simple as possible, so that you can directly compare these examples. The source is annotated with comments, so take a look and see what best fits your use case!
React's setState()
State is discussed at the start of many different React tutorials for a reason. It's included as a part of React, and is a core part of the way the framework works.
This is referred to as "local state" in the react docs, "state". Here we will call it "setState()" to differentiate from the other approaches.
setState() is a simple way to manage your application state, and doesn't require any libraries beyond just React.
There are some good reasons to use setState():
Your state is not entirely describable as plain objects (you may store unserializable state in setState(), such as DOM nodes, or objects with circular references)
Your changes are not pure functions, and depend on the "outside world" (like, the browser) to determine how state should change
You don't need a global view of the UI – your state will never be persisted or stored remotely.
✨ Example
There's annotated source available for a comparative example.
Redux
Redux is a popular alternative to using setState() when the above constraints no longer hold true. Redux is a set of tools for writing to and reading from a global state in a functional, consistent way. React redux provides a convenient way of mapping your redux state onto React components.
Async redux
For async and remote state, Redux thunk and Redux saga are popular choices. Redux thunk uses redux middleware to allow actions to be async functions, and redux saga uses a pattern that allows easy handling of async behaviour and side effects.
Redux observables is a way of allowing all the power of observables in your state management, pluggin RxJS into redux through some middleware. rxmarbles provides some great examples to give you and idea of what's possible here.
While Redux thunk and Redux saga make async state management with redux easier, but can become one more thing for developers to learn regarding state management.
⚠️ Redux is the de-facto standard for state management in React, but you might not need Redux (by Dan Abramov, a co-author of redux!). Choosing something more complicated than you need will slow you down and complicate simple state changes. This applies to other items in the list - you might not need anything other than setState().
The questions to ask are explained well in you might not need Redux, but in summary – Redux is good if you need serialisable state with an opinionated way of managing global state, but can be overkill for some use cases.
✨ Example
Apollo link state
Apollo link state is a way to combine your local state management with your remote state management. The approach assumes you are using Apollo, which allows you to use GraphQL over Rest. However, you do not need a GraphQL server in order to use this approach! – apollo-link-http allows you to write everything you need to adopt Apollo client side. This means that it's a viable all-in-one solution for state management (async and remote included), even if you aren't using GraphQL.
The way that local and remote state becomes intermingled is through your queries and mutations. apollo-link-state
gives you access to a special @client
directive that tells Apollo to look for this piece of state in local memory, rather than some remote server.
query GetTodos {
items @client {
id
text
done
}
}
Getting Apollo set up just for state management can be a bit of work, but the payoff is a natural way of querying and mutating state, combining local and remote state management.
For simple use cases, and apps that don't heavily depend on async or remote state, Apollo link state is surely overkill. For more involved use cases, Apollo can help by consolidating state management into one system.
✨ Example
Unstated
React 16 has brought with it a new context API, which is a nice way of sharing information around React's virtual tree. Unstated is a library that makes the most of this – it's a light weight way of managing global state across your application.
It's similar to Redux conceptually, but with less opinions about how you should use it. The state is not sliced up into different sections, and defining "actions" is left to you. The API is very similar to React's setState() in shape.
⚠️ Given this, if you're using Unstated, you should again carefully consider if setState() is sufficient for your use case. From the unstated readme:
The unstated readme gives good guidance about when to use alternatives such as Apollo, libraries, or Backbone models and collections.
From the readme:
Unstated isn't ambitious, use it as you need it, it's nice and small for that reason. Don't think of it as a "Redux killer". Don't go trying to build complex tools on top of it. Don't reinvent the wheel. Just try it out and see how you like it.
If you're looking for a simple, un-opinionated state management system and don't want the overhead of alternatives, it's worth looking at.
✨ Example
Honourable mentions
This is not an exhaustive list! I've included some references to alternatives not mentioned here that I haven't yet been able to create examples for or include here.
Stockroom lets you offload your store management to a web worker! This frees up the main thread from computation, and makes all of your requests to read and modify state async.
Backbone models and collections is a well known alternative, and might be sufficient for your use case.
Alfa is a very small and simple state management option.
MobX is a popular choice (hoping I get a chance to try this and add it to the blog!)
Summary
React doesn't include this type of state management itself, which leads to this rise of alternative state management systems. It can be hard to make this choice, but it's good to be allowed the choice – different problems work better with different solutions, and it's nice that React is flexible enough to work with all of them :)
👋 Hi! I’m Joshua Nelson. I’m a developer who cares about making the web a better, for everyone ✨
Posted on June 15, 2018
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.