If you've used Ignite Andross (the first Ignite stack), you know Ignite Red formerly used Redux for state management, as does much of the community. However, Ignite Red encountered some pain points with Redux so went in search of a different solution to meet our needs and landed on mobx-state-tree
. We find that it’s a great middle-ground between completely structured (like redux
) and completely freestyle (like mobx
). It brings more than just state-management to the table as well (such as dependency injection, serialization, and lifecycle events).
MST is...
- Intuitive
- With concepts like
props
andactions
, it feels familiar for React developers - Updating your data means calling functions on objects, rather than dispatching actions.
- Feels similar to relational databases, with concepts like
identifiers
(primary keys),references
(foreign keys), andviews
(calculated fields)
- With concepts like
- Streamlined
- No more
actionTypes
,actionCreators
, orreducers
- You don't have to declare your usage intentions with
mapStateToProps
; they are inferred - Side-effects are built-in; no need for 3rd party libraries like
redux-saga
,redux-observable
, orredux-thunk
- Immutability is built-in - no need for
immutable.js
orseamless-immutable
types.compose
andmodel.extend
allow for easy code-sharing of common patterns
- No more
- More than state management
- Lifecycle hooks like
afterCreate
,preProcessSnapshot
, andbeforeDestroy
let you have control over your data at various points in its lifecycle - Dependency injection with
getEnv
allows you to reference your environment (like API or other services)
- Lifecycle hooks like
- Performant
- Round-trip store writes are much faster
- Computed values (views) are only calculated when needed
mobx-react-lite
makes React "MobX-aware" and only re-renders when absolutely necessary
- Customizable
- MST ships with pre-built middlewares, including one which allows for Redux interoperability. These middlewares can also serve as examples to create your own!
We also recognize no state management solution is perfect. MST has some known downfalls:
- Integration with TypeScript is clunky at times. MST's own typing system is sometimes at odds with what TypeScript wants
mobx
andmobx-state-tree
both seem to have "magic" or "sorcery" that makes issues less straightforward to debug because you don't always have a clear picture of what's happening (but using Reactotron, which hasmobx-state-tree
support built-in, helps a lot). The MobX docs can also help illumitate some of the magic.- The user base is small, so finding help on GitHub or Stack overflow is less convenient (however, the Infinite Red Slack Community, as well as the MobX State Tree Spectrum channel are both very helpful)
- Fatal errors are sometimes too-easily triggered and error messages can be verbose and hard to grok
- The API has a large surface area and the docs tend to be technical and unfriendly
MobX and MobX State Tree can be a lot to learn if you're coming from Redux, so here are a few of our favorite resources to learn the basics:
-
Be sure to check out the official Getting Started guide for MobX State Tree.
-
There is also a free egghead.io course.
-
For a great explanation and walkthrough of the basics, check out State Management with MobX State Tree by React Native Training.
-
And for more in-depth reading, the official documentation is a great resource.
-
The official docs for MobX are another important resource, since MST is built on MobX.
-
For help from real people in the community, make sure to check out the Infinite Red Community Slack as well as the MobX State Tree spectrum channel.
-
To see example code bases using Bowser (and MST), check out these repositories:
-
https://github.com/jamonholmgren/PlayerPopularity (simple implementation)
-
https://github.com/jamonholmgren/TrailBlazers (simple implementation with hooks)
-
https://github.com/infinitered/ChainReactApp2019 (more in-depth implementation)