Hello Developers, Everyone uses various State Management library on their Application, many of us already use Redux, Redux Saga, Redux Rematch. Today we will explore MobX which is the most popular Redux alternative. MobX State Tree (MST) is the powerful state management library which you can use from small to enterprise grade applications and it’s very simple to plug & play. I will take you from core concept to component level integration, So let’s continue,
What will we cover?
MobX-State-Tree (MST) is a reactive state management library. It is a container system built on MobX.
MobX - State Management Engine and MobX-State-Tree gives you a structure which has type + state to store your data. MST is most preferable from Small to Enterprise grade application where code & functionality is going to scale periodically. Compare to Redux MST offer powerful performance and less lines of code.
MobX supports an array of features for a modern state management system and everything in one package MobX, not more extra dependency.
MST have many props compare to other state management, Lets’ check few of them,
As we discussed earlier MobX is State Management and MobX-State-Tree give you structure to store your data. So we need to install mobx, mobx-state-tree.
NPM: npm install mobx mobx-state-tree --save
Yarn: yarn add mobx mobx-state-tree
Let’s create react app,
npx create-react-app todo-app
Now, let’s install dependency,
npm install mobx mobx-state-tree mobx-react-lite
Run ToDo App,
npm run start
Let’s start by creating a ToDo application. ToDo application have two entities Task and User. Task entity have two attributes, taskName - name of task, taskStatus - to identify tasks completed or not. User entity have two attributes, userID - id of User, userName - name of User.
So, our entities will looks like something,
Tree = Type + State - Each tree has a shape (type information) and state (data). Create model with types.model
Simply create instance by calling .create()
MobX checks runtime type checking, helps developers to identify wrong data passed in argument. This is very helpful while multiple developers are involved in large scale application.
Here, You will get an error like, 95 is not assignable to type boolean, as you have take taskStatus as boolean, so you can’t pass integer data type.
The types namespace are derived from the MST package, You can check lots of widely usage types like array, map, maybe, union and many more. You can check various types available in MST.
Now, It’s time to create a root model, let’s combine Task and User model.
Note - If you are not passing default model value on .create() then you must specify default value of in second argument of types.optional(arg1, arg2).
MST - Tree node only modified in actions only.
Have you noticed self, - self object constructed when an instance of your model is created. It’s this-free, you can access it using self.
Let’s say you want to see the value stored in your state, which means take a look at a snapshot. It's simple using getSnapshot(). Every Time when you update your state and want to check if changes are reflected in the state, you can check using getSnapshot().
To listen to state change you an use this onSnapshot(store, snapshot => console.log(snapshot))
In the previous step we see we retrieved a snapshot from the model. But Is that possible to restore the model from the snapshot? Yes, it's simple. Let’s see how.
Before that I would like to relate this process with Redux, so you quickly understood. In Redux we have Reducer where we have State - and we initialize State variables with default values, like users: , tasks: ). Now first time when user open application, we haven’t any snapshot/empty store, so store will refill using model’s default value (default state value). After interaction with the application you have updated values in store. When you come back next time, it will fetch data from the store and refill your model/state. This same process we are going to do here.
In MobX we can achieve this using two different ways, First - by passing default store value, Second - passing store and default store value (snapshot value).
Now, it’s time to work with the UI, to connect the MST store to React Component we required mobx-react-lite. We are going to use an observer - name it self say everything. It’s simple, it observe store and updates React components/ Render React components whenever anything changed in the store.
In Previous steps we have rendered Tasks - for each task we have given the option to mark it complete. Now, everytime we check/uncheck the task our UI will render, because we have added an observer. It’s observer duty to update components when anything updates on the store. So, how to avoid this re-rendering situation. It’s simple let's see it.
We have separate business logic for TaskView, Note - we have added an observer in TaskView. So when anyone changes TaskStatus Check/UnCheck, only TaskView will be rendered. AppView only re-render in a case when a new task is added or existing task deleted.
Till previous steps we are showing Tasks added by User. What I need to do, to show the count of Completed Tasks and Pending Tasks? It’s simple with MobX, add getter property in our model by calling .views, it will count how many Tasks completed and pending. Let’s see the code.
Now, it’s time to assign a User for each Task in Tasks. For this we need to tell MST which is the unique attribute (primary key in db language) in each User model instance. You can implement it using types.identifier type composer.
Now we need to define a reference to the Task Model. It’s simple - you can do it using types.reference(User). Many times it’s a circular reference, so to resolve it we need to use types.late(() => User). It may be possible User entry found null, to resolve that we need to use type.maybe(...), So finally let’s see how code looks like,
We have covered almost all required topics from MobX-State-Tree. MobX provided few sample example, download ToDoMVC - app using React and MST and Bookshop - app with references, identifiers, routing, testing etc.
Thanks for reading Blog!
Get tech aricles directly in your inbox! Share your email with us and receive tech articles as instant as we publish!