Posted: - Updated:

MobX + React Tutorial: Building your first App.

Categories JavaScript, Tutorial

Last week we went over the main principles of MobX, as well as why mixing it with React is an amazing idea. That covers all of the basics that we need and sets common grounds of understanding. Which means we can now focus on building our first application using the two of them. And that’s what we’ll be doing in this MobX + React Tutorial.

Our first MobX + React Application.

We’re going to be building an App called a List Detail View. The App will render out a list of one line “summary” components for larger pieces of data. Additionally, clicking one of them will render a second component containing more detailed information.

In this way you click on a list element to view its details. List Detail View. Simple enough right?

See the Pen #100DaysOfCode: (React + MobX) List Detail View by Orlando Paredes Hamsho (@orliph) on CodePen.

The application above is a direct embed from my Pen at Codepen.io, which was the first place where I coded this tutorial. (It is also a good place to grab the CSS, because I won’t be explaining it) And that’s one of the points I would like to make about this tutorial:

We’ll be writing code so concise that it wouldn’t be out-of-place for it to be in a single file.

And that’s only a result of the simplicity and lack of boilerplate that MobX itself provides. The Store itself is not even 20 lines of code. 

But that’s enough praising MobX, let’s continue.

On the previous post I gave away a few freebie starter packs. However, I’ll link to them again here, in case you want to use them to follow along:

Now that we have common ground to start on, the first thing we have to do is create the view side of our app. And, just to be clear, I will be assuming that you’re following along from the GitHub Starter pack, as it’s the closest to a real-world situation. Or at least the closest I provided.

The React Side of our application.

Word of advice, for these few sections focusing on React, I am expecting you to have some general knowledge on the topic. If you don’t, my article on React Fiber is a great place to get started, as it covers the basics and give out resources to further your knowledge.

I repeat, I will not be explaining myself every step of the way until we hit the MobX part. However, I will only be pointing out design aspects and things I find interesting.

Starting with our First React Component.

Let’s look at our first component, the Profile Component. This one will render a single element of the List part of our application. It renders just enough data to identify it while making us want to click it:

// src/components/Profile.js
import React from 'react';
import PropTypes from 'prop-types';

const propTypes = { 
    onClick: PropTypes.func, 
    selected: PropTypes.bool, 
    label: PropTypes.string,
};

const Profile = ({ onClick, label, selected }) => { 
    //If it's selected, highlight it. 
    const classes = selected ? 'bold' : ''; 
    return ( 
        <li onClick={ onClick } className={classes}> 
            { label } 
        </li> 
    );
};

Profile.propTypes = propTypes;
export default Profile;

So I believe right away we have some questions. Let’s start from the top:

  • The first lines of code are Import statements, which allow us to migrate certain pieces of code from other files onto ours.
    • We bring in React because it has to be a part of every file that we use React Components in.
    • And we also import a library called ‘prop-types’. It allows us to define the variable type for each of the properties in our component.
  • Then we define our Component’s propTypes at the very top inside their own variable. We do this to make it easier to see, at a glance, what properties our component makes use of. This is in favor of creating better user interfaces out of our code.
  • Next we create what is known as a Stateless Functional Component. This means our component will be a function meant to display data, while having very minimal logic.
    • You may notice the syntax on the component we’re building. It’s in the shape of an Arrow Function with De-Structured Arguments. I talk more about them in This Article.
  • You may also notice we’re using a Ternary Operator to set the classes variable based on one of our properties.
  • We assign the propTypes variable to our Component’s propTypes.
  • And, finally, we expose our component to the rest of our application by using the export keyword.

I’d like to take this opportunity to make a point here. The profiles component is made to be intentionally generic. Mainly because it makes the component easier to re-use. Especially since all you would need is to give it a label to have it render.

Displaying our selection with a React Component

Our next component represents the bigger subset of data that we render on clicking a particular list item. The Detail part of our List Detail View:

// src/components/Selection.js
import React from 'react';
import PropTypes from 'prop-types';

const propTypes = {
 user: PropTypes.object
};

const Selection = ({ user }) => ( 
    <ul> 
        <li>Name: { user.name }</li> 
        <li>Username: { user.username }</li> 
        <li>Phone: { user.phone }</li> 
        <li>Email: <a href={`mailto:${user.email}`}>{user.email}</a></li> </ul> ); Selection.propTypes = propTypes; export default Selection;

Once again we keep it generic. Which means this component will work as long as we give it an object, even one that’s empty.

However, one thing to note here is the ‘mailto’ href with a Template String.

  • First, Template Strings are an ES6 Feature that will automatically interpolate values in between ‘${}’ characters. Although that is only one of their many graces. You can read more on them here.
  • Second, the ‘mailto’ href will automatically open an email client with an email directed at whatever address comes after the colon. And, of course, it will allow you to modify it.

I hope by now we’re getting the hang of this. Because now that we have our two building blocks, we need a place where to use them.

The react side of our main Class Component.

Our next main component will integrate our previous both, forming a little bit of a Container of sorts. Additionally, we’ll be using this component to interact with our MobX store.

For this reason, the explanation itself will be divided in two parts: A React part and a MobX one.

Let’s start with the React one. The App component has to render a list of Profiles, as well as making sure that, on clicking one of them, a Selection is rendered. So let’s handle that:

// src/components/App.js
import React, { PureComponent } from 'react';
// Covered in the MobX Section 
import { observer, PropTypes } from 'mobx-react';
// Covered in the MobX Section 
import _ from 'lodash';

// Relative imports
import Selection from './selection';
import Profile from './profile';

const propTypes = {
    store: PropTypes.object
};

// Observers can react (ba dum tss) to changes in observables
@observer
class App extends PureComponent {
    componentWillMount() {
        this.props.store.getUsers();
    }
    renderSelection(){
	if (_.isEmpty(this.props.store.selectedUser)) return null;
	return (
	    <div className='selection'>
		<Selection user={this.props.store.selectedUser}/>
		<button onClick={this.props.store.clearSelectedUser}>
                    Close Profile
                </button>
	    </div>
	);
    }
    renderProfiles(){
	return this.props.store.users.map((user) => (
	    <Profile
		selected = {user.id === this.props.store.selectedId}
                key = {user.id}
		label = {user.name}
                onClick = { () => {this.props.store.selectUser(user)} }
	     />
	));
    }
    render(){
	return (
	    <div>
		<h3>Employee Directory</h3>
		{this.renderSelection()}
		{this.renderProfiles()}
	    </div>
	);
    }
}

App.propTypes = propTypes;
export default App;

And this is where things start to get a little bit interesting. Let’s start with the general parts:

  • Instead of including just React, we’re also importing a class called PureComponent. Which is just like a regular component, except a little more efficient. However, information on Pure Components can be found here, if you’re interested.
  • We’re also importing Lodash, a JavaScript utility library. Which, amongst other things, excels at manipulating collections (Lists of Objects).
    • We mainly use the _.isEmpty() method of Lodash to decide on whether or not to render Selection.
  • There’s also syntax for Relative Imports. Which means you write the path to the file you want relative to the one you’re writing in. This is how we get access to our previous two components.
  • Next we note that this component is in fact Class based. Meaning we’ll be handling more logic inside it, as well as accessing it’s life-cycle methods.
  • Finally, note that we are using Helper Rendering Functions to handle the more complicated aspects of our logic. This leaves the actual render method to be as concise as possible.
    • The renderSelection method decides on when to render the Selection, as well as a button to close it.
    • And the renderProfiles method takes care of rendering a list of Profiles based on the users array of our store.

The MobX Side of our application.

From this point out I will do my best to explain everything, every step of the way. Especially since that is what we’re here for in the first place. So, let’s start looking at our App.js file again:

The MobX side of our main Class Component.

// src/components/App.js
// ...
import { observer, PropTypes } from 'mobx-react';
// ...

This is the first line of notice, importing observer from a library known as mobx-react. As we discussed in the previous post, MobX is a State management solution, and not directly linked to React. For such reasons mobx-react represents a set of bindings to allow both MobX and React to work together.

The method observer in particular is used to modify an existing component so that it responds to changes in a MobX Store. But we’ll get into what a Store is soon enough.

Additionally, I wanted to point out that MobX has its own set of PropTypes. They contain everything regarding observables and are extremely useful when combining MobX with React.

// ...
@observer class App extends PureComponent {
// ...

A little note here, we are using the observer method as a decorator. Which means using it as a function that adds functionality onto our class without directly modifying it. They’re part of proposed ES6+ syntax but not yet an official part of the language. You can find more information on decorators here.

//...
componentWillMount() { this.props.store.getUsers(); }
//...

Finally, here we can see an example of how the store will be used throughout this component.

It gets passed in as props and we use different methods (called actions) to interact with it. Additionally, we’re using our store here inside a life-cycle method, particularly componentWillMount, which will get called right before our component’s first render.

And we can see examples of the store getting used in different parts of the app:

  • <button onClick={this.props.store.clearSelectedUser}> as an on click handler.
  • <Profile selected = {user.id === this.props.store.selectedId} // ... as a condition for being selected.
  • And even renderProfiles(){ return this.props.store.users.map((user) => ( // ... as an array to map over.

But now we’ve teased enough about the store, time to actually build it.

Our MobX Store.

A store represents a subset of application data. You can have multiple stores (as Flux suggests) or encompass everything into a single one (which is the way that Redux handles it.)

However, the main idea still stands that the store should represent the single source of truth for a particular subset of application data. That way we can make sure our application is always reacting to the right information.

With that being said, let’s look at our store:

// src/models/UserStore.js
import { observable, action, computed, useStrict } from 'mobx';
import axios from 'axios';

useStrict(true);

class UserStore {
    // Values marked as 'observable' can be watched by 'observers'
    @observable users = [];
    @observable selectedUser = {};
    @computed get selectedId() { return this.selectedUser.id; }
    // In strict mode, only actions can modify mobx state 
    @action setUsers = (users) => { this.users = [...users]; } 
    @action selectUser = (user) => { this.selectedUser = user; }
    // Managing how we clear our observable state
    @action clearSelectedUser = () => { this.selectedUser = {}; }
    // An example that's a little more complex
    @action getUsers() {
	//Managing Async tasks like ajax calls with Mobx actions
	axios.get('http://jsonplaceholder.typicode.com/users').then( response => {
	    this.setUsers(response.data);
	});
    }
}

const store = new UserStore();

export default store;
export { UserStore };

And, just like with our component, we’ll be breaking things down little by little here:

// ...
import { observable, action, computed, useStrict } from 'mobx'; 
import axios from 'axios'; 
// ...

First we’ll be importing the main building blocks of our application:

  • MobX observables. Pieces of state that cause reactions and computations in response to their own changes.
  • Actions. Nothing too special about them, they’re just functions that are allowed to modify state in Strict Mode.
  • Computed observables. Pieces of state that are derived from Observables.
  • And useStrict, a method which we’ll use to activate Strict Mode.

If you’re wondering about Reactions, don’t be. Just like I explained in my previous post, React is taking care of most side effects that result from altering our observable data. React is handling our reactions.

The other thing to note here is that we’re importing Axios, a very popular library for handling Ajax calls.

// ...
useStrict(true);
// ...

Here we are activating Strict Mode: which enforces that all modifications to our observable state must be made by actions. It adds a little bit more predictability to our system.

Note: If it were me I would have it the default mode. But I can see why they chose not to (less boilerplate.)

//... 
class UserStore { 
    @observable users = [];  
    @observable selectedUser = {}; 
// ...

Two things of note here:

  • Our MobX Store is going to be a regular ES6 Class, which have similar syntax to what most of us are used to. This plays into the familiarity topic that I was talking about earlier. Because it is a regular old class, it gives us a little bit of certainty and lets us stand on familiar ground.
  • The Observables themselves are just properties of the class marked with the @observable decorator.
  • This means that you can, in fact, have properties in your store that are not observable. Just don’t prepend them with the decorator.
// ...
@computed get selectedId() { return this.selectedUser.id; }
// ...

Computed values are represented as getter functions in our Store Class. Which means that they will become available afterwards as properties (without having to call the function.)

For example, selectedId in: <Profile selected = {user.id === this.props.store.selectedId} />.

//...
@action setUsers = (users) => { this.users = [...users]; } 
@action selectUser = (user) => { this.selectedUser = user; }
// Managing how we clear our observable state
@action clearSelectedUser = () => { this.selectedUser = {}; }
// An example that's a little more complex 
@action getUsers() {
    axios.get('http://jsonplaceholder.typicode.com/users').then( response => { 
        this.setUsers(response.data); 
    }); 
// ...

Over here we’re finally dealing with actions. Simply put, we’ll be directly mutating state using them. Some simple examples include just setting data. While more complicated ones like getUsers can even use external libraries to fetch said data.

However, because we’re using strict mode, trying to modify the store inside the.then statement would lead to an error. So we use an action instead.

Additionally, it is important to note that we created clearSelectedUser so we could be the ones to decide how we’re going to be resetting our own state. It brings a little bit more control.

It’s also worth noting that we’re declaring all our actions as Arrow Functions. This allows the context of This to be bound automatically. And that way we don’t have to worry about losing it

// ...
const store = new UserStore(); 
export default store; 
export { UserStore };
// ...

Finally, we export both our store and an instance of it.

Note: There are different approaches as to how we handle our stores. One suggest exporting an instance of said store and using it as a singleton. The other suggests having different stores, each with its own subset of data. It’s really up to your preference and the situation.

Putting it all together.

As it stands we only have to render our App component to an Html Node and pass it our store. So we’ll be doing just that:

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
// Relative imports
import App from './components/app';
import store from './models/user-store';

ReactDOM.render(<App store={store} />, document.querySelector('.container'));

As this file isn’t really all that big, I’ll do all of my explaining right here.

  • We import ReactDOM, which allows us to actually render our application to an html element in our page by means of ReactDOM.render().
  • We also import React, as well as both our main component (App.js) and an instance of our store.
  • Finally, as we’re rendering our main component, we pass in the store instance to it as a prop.

And that’s basically it. This way our store will get passed down to App, which will use it to gather, render and manipulate the data our store contains.

  • The store will get the data it needs when the componentWillMount life-cycle method is triggered.
  • It will then use this data to render each one of our Profiles by mapping over it’s users array.
  • Clicking any of the profiles will cause us to populate the selectedUser state. The Selection component will render with its data as a direct reaction to that.
  • Additionally, having a selectedUser will cause selectedId to compute as a reaction. This will in turn highlight one of our Profiles.
  • Finally, we can click the ‘Close Profile’ button to reset our selectedUser, and bring everything back to the start.

If you have all the starter pack from github, you can switch to the mobx-react-list-detail-view app for the full tutorial code. You can also look at this pen for a lighter version of the same.

Wrapping up our first MobX + React Application.

What we covered here today is a very simple example of what building an application using MobX is like. However, all of the concepts we learned will translate perfectly into a production environment.

I’m also aware that my explanation isn’t perfect. There may be things that seem obvious to me but probably aren’t. But if anything, I’m hopeful that I at least managed to break the ice and show you that MobX isn’t really all that complicated. And that mixing it with React isn’t rocket surgery.

There are many topics that are still left to be covered: Testing, Linting, Strategies for scaling with MobX; and many more. Most of which I think I’ll be leaving in the hands of more experienced people.

And, if this picked your interest, the main MobX page has a very comprehensible list of resources you can use to keep learning.


Being completely honest, I’m not the biggest fan of writing tutorials myself. I would much rather discuss a topic or tell a story. Something that should be glaringly obvious looking at my site.

However, MobX is a topic that I find myself deeply passionate about. Maybe it’s because I work with it literally everyday. Perhaps it’s because of how much better it makes my life as a developer.

Regardless of my reasons, I knew I wanted to help to increase the awareness of this wonderful State Management Framework.

It’s my first time writing a tutorial, if that much wasn’t obvious already. So I invite you guys to let me know if there’s any way I can improve in this craft. Everything from parts of the tutorial where you got lost to anything I didn’t make clear.

All constructive criticism is welcome and I invite you all to help me improve in the comments section. Thank you and see you next week!

My name’s Orlando Paredes Hamsho. I’m a 25-year-old Web Developer living (mostly) in Guadalajara, Mexico; albeit I intend to move pretty soon. Apparently, I also run a blog now, and have been doing so for a while.

4 thoughts on “MobX + React Tutorial: Building your first App.

  1. Shouldn’t we use componentDidMount instead of componentWillMount?

    React Docs –
    “componentDidMount() is invoked immediately after a component is mounted. Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request. Setting state in this method will trigger a re-rendering.”

Leave a Reply

Your email address will not be published. Required fields are marked *