Web Programming TutorialsKnow Everything About Managing Reactjs State with Mobx

Know Everything About Managing Reactjs State with Mobx

Mobx comes up with an ideology that using it will be easier to manage state in a ReactJS application rather than the commonly used Redux. Managing state in a Reactjs application that tends to scale over time can be a complex task if not done gracefully. Foundation of managing state in React is triggered by the good old setState function which is okay if your application is easier to organise and does not have more than 4 to 5 components or screens. If you are in the React world there are some pretty high chances you may have heard about Mobx. Its latest version 5 was released two months back and is developed by Michel Weststrate. In this tutorial, we will be building a simple Reactjs State application that will guide you through setting up, exploring the concepts it revolves around and finally building a small application.

What is Mobx? A high overview

Mobx as a state management library is currently being used by companies such as Facebook, Lyft, Wix and Coinbase. The core of Mobx applies functional reactive programming concepts into practical applications. The philosophy behind Mobx is that “Anything that can be derived from the application state, should be derived. Automatically.” A more clearer picture is provided by this image below.

Mobx

React and MobX together is a powerful combination. React renders the application state by providing mechanisms to translate it into a tree of renderable components. MobX provides the mechanism to store and update the application state that React then uses.

Core Concepts in Mobx

Mobx has only few core concepts. We will first take a look at them and then will use them in our application. The first one is the observable state. Mobx takes advantage of ES.Next feature called Observables. This is nothing new. Observables have been a common practice in libraries such as Rxjs with Angular for more than a year.
Observables extends existing data structures like objects, arrays and class instances. This can simply be done using @observable decorator. In simple terms, observables define application state that a component has access to.

import { observable } from 'mobx';

class Todo {
    @observable title = '';
    @observable finished = false;
}
import { observable } from 'mobx';

class Todo {
    @observable title = '';
    @observable finished = false;
}

These values, of title and finished are primitive values that refer to objects and arrays of their own. The next is to derive these values automatically when the relevant data or the value is modified. This is done by @computed decorator.

class TodoList {
    @observable todos = [];

    @computed
    get unfinishedTodoCount() {
        return this.todos.filter(todo => !todo.finished).length;
    }
}

You can think of computed values as those values that are derived from the state. The last concept is called Reactions that are similar to computed value but unlike computed values who produce a new value, a reaction produces a side effect for making network request, incrementally updating the React component tree to patch the DOM, etc. It acts like a bridge between the reactive programming fundamentals and imperative fundamental that Reactjs follows. You can make your stateless components reactive by adding the observer decorator.
If any of this not making sense, do not worry, things will get clear once we start working on our application.

Managing Reactjs State with Mobx

To use mobx in Reactjs environment, we have to install a few dependencies. But first, let us install and generate an application for Reactjs.

npm install -g create-react-app

create-react-app react-mobx-example

Once our project is successfully generated, traverse inside the directory and install the following dependencies.

npm install --save mobx mobx-react babel-plugin-transform-decorators-legacy

Inside .babelrc we need to need the support for plugin which will further allow us to use ES.Next features such as decorators in our React components.

{
    // omitting pre-existing configuration, if any
    "plugins": ["transform-decorators-legacy"]
}

Now, create a new file called Todo.js.

import React, { Component } from 'react';

export default class ToDo extends Component {
    render() {
        <p>You have 0 ToDo items</p>;
    }
}
import React, { Component } from 'react';
import { inject, observer } from 'mobx-react';

@inject('toDoStore')
@observer
export default class extends Component {
    constructor(props) {
        super(props);
        this.toDoInput = React.createRef();
    }

    handleSubmit = e => {
        e.preventDefault();
        this.props.toDoStore.addToDo(this.toDoInput.current.value);
        e.target.reset();
    };

    render() {
        return (
            <div>
                <p>You have {this.props.toDoStore.toDoCount} ToDo items</p>
                <ul>
                    {this.props.toDoStore.toDos.map(toDo => (
                        <li key={toDo}>{toDo}</li>
                    ))}
                </ul>
                <form onSubmit={this.handleSubmit}>
                    <input type="text" placeholder="Add a ToDo" ref={this.toDoInput} />
                </form>
            </div>
        );
    }
}

Import this component in our App.js.

// ... after other imports
import ToDo from './ToDo';

class App extends Component {
    render() {
        return (
            <div className="App">
                <ToDo />
            </div>
        );
    }
}

ToDo items

export default App;
Run the application from the terminal to see this in action using npm start.

The next step is to create store that will take care of adding todo items to the current state(which we also define in this step) and counting them to dsipay the item count in our app. Create a new file ToDoStore.js.

import { observable, action, computed } from 'mobx';

class ToDoStore {
    @observable toDos = [];

    @action
    addToDo = toDo => {
        this.toDos.push(toDo);
    };

    @computed
    get toDoCount() {
        return this.toDos.length;
    }
}

export default new ToDoStore();

Actions are anything that modify the state. addToDo is an action and it modifies the state of our app by adding a new todo item. We have defined a toDos array using observable which is our state andwe modify it inside the addToDo action. The next is computing the length of toDos array which is done by @computed decorator. It defines another method using a getter/setter approach toDoCount and returns the length of the toDos array from our state. Note that acrions in mobx are functions. Whereas, in Redux actions are objects. Lastly, we export the our Todo store to use it in ToDo.js file. Open and modify it.

import React, { Component } from 'react';
import { inject, observer } from 'mobx-react';

@inject('toDoStore')
@observer
export default class extends Component {
    constructor(props) {
        super(props);
        this.toDoInput = React.createRef();
    }

    handleSubmit = e => {
        e.preventDefault();
        this.props.toDoStore.addToDo(this.toDoInput.current.value);
        e.target.reset();
    };

    render() {
        return (
            <div>
                <p>You have {this.props.toDoStore.toDoCount} ToDo items</p>
                <ul>
                    {this.props.toDoStore.toDos.map(toDo => (
                        <li key={toDo}>{toDo}</li>
                    ))}
                </ul>
                <form onSubmit={this.handleSubmit}>
                    <input type="text" placeholder="Add a ToDo" ref={this.toDoInput} />
                </form>
            </div>
        );
    }
}

First we use @inject(‘StoreName’). This injector will help us to inject store in our component and access it as props. We also make the ToDo class an observer. Now our ToDo component can access the count of Todo items in from the state. Do not render the application, we are still missing an important piece. We have to use Provider for the store to inject properly in our ToDo component. Modify the App.js file accordingly.

import React, { Component } from 'react';
import './App.css';
import ToDo from './ToDo';
import ToDoStore from './ToDoStore';
import { Provider } from 'mobx-react';

class App extends Component {
    render() {
        return (
            <Provider toDoStore={ToDoStore}>
                <div className="App">
                    <ToDo />
                </div>
            </Provider>
        );
    }
}

export default App;

Now run the npm start command, add few items using the input. You can see it working as following.

demonstration

This is example is for demonstration purposes. Where ever you can use Redux to manage state in a React app you can use Mobx.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Exclusive content

- Advertisement -

Latest article

21,501FansLike
4,106FollowersFollow
106,000SubscribersSubscribe

More article

- Advertisement -