TLDR; MobX for 1–3 people or small apps, Redux for anything beyond that.
Lately, I have been researching and using MobX and Redux for a project that would most likely evolve over the next few years into something to the scale of JIRA. After skimming reading way too many articles, discussions, and taking the time to build two apps out of both technologies, I nailed it down to these three resources that I felt best explains the key differences and use cases are for MobX and Redux.
MobX — Simple, scalable state management for React
Understanding MobX and when to use it. #199
Understanding MobX vs Redux
Take a minute to read those threads. The arguments remind me a lot of the old days when people were trying to decide between Backbone v. Angular and Angular v. Knockout.
What I Learned
- Easier to test, easy to achieve 100% test coverage.
- Predictable deterministic state makes it easy to debug.
- Scales well to large teams out-of-the-box.
- Opinionated. There is only one way for data to flow.
- Opinionated. You work slower because you have to follow a pattern even for trivial things.
- Steeper learning curve. Required firmer grasp of ES6 and ES7 concepts to use effectively, as well as Flux.
- More boiler plate code.
- Faster to code as there is more auto-magic similar to two-way data binding, and thus less code.
- No need to learn or understand the concept of Flux.
- More flexible. You decide how to maintain state.
- Freedom. You can make state work with you.
- Only scales well to large teams IF maintained and organized correctly from the start (you’re at the mercy of the genius from first few people who started the project).
- Too much freedom. Easy to build something in a non-scaleable way.
- While you can use MobX to build something Flux-ish, it’s also easy to deviate.
This comment from rwieruch on Hacker News summed it up best for me:
I agree that for most users Redux feels like a lot of boilerplate. At the same time I think most people underestimate were we came from. Personally I wrote a huge amount of Angular code before and at a certain point I felt very unhappy about the two-way data binding and state handling in Angular. It was unpredictable in a huge code base at some point. Then it was the time of Flux and in our company we introduced a stores and unidirectional data flow implementation of our own. Afterwards Redux got announced and we loved the clear constraints and lightweight API from the beginning. We use it now.
In a team of developers everyone can clearly follow state changes, the state itself and the places from where the state changes were triggered. Redux is scaleable and shouldn’t be used for every small project which could live without a state management library and should use setState instead. Redux simply works, even though you have already a big amount of actions in production.
I think MobX is on the right path to give an alternative way for state management. For now I see a clear benefit to kick off smaller projects in smaller teams which don’t rely on Redux’ constraints and scaleability. Little feature op-tins like useStrict will help MobX to have a more scalable state management system. Otherwise in a growing code base it will feel like the old Angular days with two-way data binding. In the end that is the power of MobX, because it isn’t opinionated: You can either mutate your state directly in a component or build a proper infrastructure around it to make it scale.
I will always push for Redux in groups greater than 3+ due to its extreme predictiveness, which I find invaluable as something grows. To me, we have to remember where we came from. DHTML -> jQuery -> Backbone vs. Knockout vs. Ember -> Meteor -> Angular vs. React. In many cases, state management became biggest source of bugs and trouble, which is why Flux was introduced, and ultimately Redux. MobX is a great tool and recommends you to use it in a Flux inspired way, but it is reminiscent of Knockout JS and other MVVM libraries back in the day, where the magic worked out at first, but 6–12 months later, the magic and freedom was bad news as developers implemented various solutions in ways that worked for them leaving bugs hard to track down.
Having previously oversaw an app grow from scratch to JIRA size, I found as the team and project grew, two key things that slowed us down were lack of predictability, lack of testability and code variance. One could argue that these things should have been caught at code review, or these best practices should have been more enforced during review, but anyone who has worked at a quickly growing company knows that all of the above is a luxury. With Redux there is a less chance of things getting too out of control. This implicit predictability in your code base invaluable to a growing company as you never know what kind of engineers will join your team or what true skill level they have.
While Redux is not as flexible, it has clear constraints, and state is very deterministic making it easy to debug issues. While you can design MobX state to be more predictable through the use of its useStrict feature and good design, its freedom is also weakness, as it isn’t explicitly enforced thus leaving the door wide open for a single developer to mess up the code if it gets past code review.
For personal usage on a small app, or with a friend I can easily communicate with and thinks like me, I would use MobX because I don’t really need to share the code with anyone, and MobX gives me the flexibility to develop how my mind feels in that moment. However, if I know people who I am unfamiliar with might be joining me on a venture (which is almost every work environment scenario), or am building something I hope one day will be huge, I will use Redux due to it’s built-in standardization.