State management is hard. Just ask any President, Senator or frontend dev. Dad jokes aside, state management in JavaScript (and React specifically) is a hot topic for discussion. Sure, you can use this.setState
and this.state
in your code at first. But as soon as your application grows beyond simple functionality, you will have to address the challenges of React application state management.
The best practice is to tackle this predicament sooner rather than later in the development process. The sooner you adopt a state management approach and library for your project, the less code you will be forced to rewrite as the size and complexity of your code-base grow.
Fortunately for you, you are (by far) not the first person wondering what state management approach to implement in their React frontend application. There are quite a few choices out there, with two framework-agnostic external libraries gaining the most popularity over the past few years: Redux and MobX.
While both Redux and MobX aim to solve the same challenges and address the same issues, they are quite dissimilar. Each has its pros and cons, and a radically different approach to state management in React. Before we can compare them, let’s take a short dive into the core principles of each.
Redux defines itself as “a predictable state container for JavaScript apps”. It was created in 2015 by Dan Abramov and Andrew Clark, looking to create a state management for the React framework. In essence, Redux is a combination of Facebook’s Flux architecture and functional programming concepts drawn from the Elm programming language.
The core principles of Redux are:
MobX is a library that aims to make state management simple and scalable by transparently applying functional reactive programming (TFRP). According to the readme, the approach of MobX is thus: “Anything that can be derived from the application state, should be derived. Automatically.” This includes the UI, data serialization, server communication, etc.
In addition, some of the core principles of MobX include:
Our short introduction to MobX and Redux makes it obviously clear that the functionality they offer and the impact on your workflows differ greatly. There is no doubt that the main criteria for choice is personal preference and coding “style”, as well as project needs. That said, there are some criteria where there is an obvious “winner” between Redux and MobX.
In Redux, there is only one store. It serves as the single source of truth containing normalized data. Redux state is immutable and for each new state, an ancestor state is cloned.
This makes it easier to know exactly where to find the data/state. The downside of this is that the store can quickly turn into an enormous .json file. The upside is in the intuitive nature of this approach. For most developers working on large React projects, having a single source of truth to refer to can be a huge advantage.
Unlike Redux, MobX usually maintains at least two stores – one for the UI state and one (or more) for the domain state, and they contain denormalized data.
The advantage of multiple stores is in the ability to reuse and query the domain state universally, including other applications. All the while, the UI store would remain specific to the current application.
The disadvantage is clear – multiple stores can quickly lead to clashes and unpredictable results when multiple applications make changes to the domain state.
Redux uses simple JavaScript objects as the data structure to store the state. This requires that updates be tracked manually. Which can add quite a bit of overhead when it comes to applications with complex states to manage and maintain.
MobX uses observable (or noticeable) data to automatically track changes through subscriptions. Quite clearly, automation makes for an easier life for a developer. So it’s no wonder many find MobX to be an obvious winner in this category. It’s simply more comfortable to use.
We’ve already established that Redux uses a single, immutable source of truth for the states stored. This means that states are all read-only, and reducers can overwrite a state invoked by an action. Reducers are pure functions, as they receive a state and action and return a new state.
On the flip side there’s MobX that allows for states to be easily updated and overwritten with new values. While it may be easy to implement, testing and maintaining can become a nightmare of unpredictable outputs.
Perhaps one of the main shortcomings of Redux is the sheer volume of boilerplate code it brings. This is especially true when it comes to React applications.
Since MobX is a lot more implicit in nature, it packs a lot less boilerplate. In this category, MobX is a clear winner.
The purity and somewhat rigid approach of Redux is an advantage when it comes to scalability and debugging of applications. The predictability of pure functions makes Redux much easier to test, maintain and scale than MobX.
As mentioned above, Redux is a lot more predictable than MobX as it comes with a lot less abstraction. Add to that a superior set of developer tools (including time traveling) and you got yourself code that is a breeze to debug.
Unlike Redux, MobX relies a lot more on abstraction, which can produce unpredictable results and generally make debugging difficult. Moreover, the lack of efficient tools for MobX debugging and testing add another hurdle for developers considering MobX for their state management needs.
The path to Redux proficiency is a long one, but those who’ve traversed the steep route claim it’s worth it. This is especially true for developers coming from an object-oriented programming background. Being a combination of Flux and functional programming concepts, Redux is easier to stomach for those with experience in functional programming.
Moreover, employing Redux demands that you learn to work with Redux middleware like Redux Thunk, making the learning curve steeper still.
Since most JavaScript developers are well familiar with object oriented programming, MobX comes naturally to them. With a lot of built-in abstraction, MobX demands a lot less “typing” and results in a lot less boilerplate code. In addition, there is no need to use middleware to implement MobX in your application so learning it is an obviously faster and easier experience.
Comparison articles often consider popularity and a large user community to be critical in choosing a framework or library. Though this is not a popularity contest, there is value to the prevalence of a technology.
More developers using the library means more answers on StackOverflow or Tabnine’s JavaScript Code Library, for that matter. It means better maintained project source code, as well as clearer documentation, and a selection of tools and enhancements.
So which takes the crown in the popularity content? There’s actually no contest as Redux is far ahead of MobX when it comes to community support and prevalence.
Redux has Redux Dev Tools used by thousands of developers debugging Redux code. GitHub stars and contributors? Redux wins. Google Search popularity in 2020? Still Redux. Same is true for npm downloads as well.
As always, there’s no one size fits all and no rule of thumb to guide you in choosing the perfect state management library and approach for your React project.
If you’re looking for a library with the best support, developer community and is built to scale? Redux is probably your answer. However, if you are pressured for time and need to implement state management in a simple proof of concept app? MobX could be the way to go.