Understanding Mobx — behind the scenes

Lokesh Pathrabe
4 min readMay 23, 2020

If you are into front end web development and working on ReactJs, good chances that you are using Redux as your state management library. As most of us are. Redux is a widely popular lib for React applications and why should it not be. It is simple, scalable and solves all your sync and async problems with a wide variety of tools and add-ons available.

But it's not the only one out there. There are a bunch of alternatives that might work for you. One of them is Mobx. I am writing this to discuss my understanding of this library and how it works.

Before we proceed you would need to familiarise with some concepts of Observable pattern and Reactive-JS. Here are a few links to get started quickly.

Observable Pattern,
RxJS.

Introduction to Mobx

Mobx works on Observable pattern where your app state is observable (subject) and your presentation components are observers (subscribers). Observer component would re-render whenever the observable state is mutated. That's it! No reducers, action creators, middlewares boiler code. The app looks really simple. More on the mobx concepts here.

A simple observable state

To understand how mobx works and what it reacts to, we will create a small observable state of our own and make our observer component react to its changes. This will help in understanding how mobx works behind the scenes. We would use RxJS to create our state and a React component.

Create an observable state

In the above code snippet person is our state. We add a new property firstName to it and define get() and set() methods. We wrap this in an RxJS observable function and create a new observable object. Whenever we set a value on firstName the observe.next() is called which would rerender the observer component. How? Let's see.

Observer component

Now we just need to bind our component to observable state such that whenever the setter function is called our component would rerender. Let's see an example in React.

On input change `person.firstName = e.target.value; ---> observe.next() ---> () => setState({}) ---> rerender <App/>

So, now that we know how an observable state would work with a react component, let's create a mobx app.

Mobx State

Mobx provides 2 ways to create state and components

  1. Wrapper functions like Observable({...state })
  2. Decorators like @observable const state = {}.

In this example, we will use functions as annotations are still not part of official ES and you will need to configure babel to use them.

We created a primitive, nested object and array state objects. We need to pay special attention to how we create the state and how we mutate it. Because mobx will not react to mutations if this is not done correctly. We discuss this further in the article.

Observer(<App/>) creates an observer component. We directly import our state and use it in the app. Mobx will keep a watch on all observable state that we use in this app and rerender our component when state mutates.

A couple of points to note:

  1. We import observer from react-mobx a react specific lib from mobx.
  2. We need to call get() method on primitive values created using observable.box(). Other state properties can be assessed directly.
  3. An observable state is a mobx object wrapping our actual state values. Notice that we use toJS to get the actual object toJS(state.indiaScores).join(", ") This needs to be done before access the state values for something like sending as API params.

Now we define the actions that will mutate our state

A couple of points to note when mutating a mobx state.

  1. Your action should be wrapped in action() or use @action annotations. Mobx also provides other APIs like runInAction() for inline actions.
  2. For primitive properties created using observable.box() we need to use set() and get() methods on the property. These are exposed by the observable state created by mobx.
  3. When mutating a property on a nested object we need to mind the level which we are changing. For example.

state.score.india.kohli++; // triggers rerender

but


let score = state.score.india.kohli;
score += 1;
state.score.india = { kohli: score }; // Does not trigger rerender

Reason being the observable component is observing property 'kohli'. When the setters on kohli property are called, only then the observer will be notified of the change triggering a rerender. This is clear from our Observable state example earlier.

I hope this was helpful and easy to understand. This example is available on codesandbox if you want to play around.

Thanks for reading.

--

--

Lokesh Pathrabe

Web developer working mostly on ReactJS and other react eco system tools and technologies.