Categories
Mobx

Simple State Management with Mobx

Spread the love

Mobx is a simpler alternative to state management for React apps. It works by creating a store and then watching it for changes, and we update the store by changing the values directly.

In this article, we’ll look at how to use Mobx and React together.

Installation

We install the mobx and mobx-react libraries to create our Mobx store and then connect it to our React component.

To do this, we run:

npm install mobx mobx-react

All modern browsers are supported by Mobx with version 4.x or earlier. Since version 5, Mobx uses proxies for state updates so Internet Explorer isn’t supported. It also works with React Native and Node.js

Basic Usage

To start using it, we create a store to hold the state. Then we can pass the store into our component.

For example, we can use Mobx to create a store then inject the store into our React component as follows:

import React from "react";
import ReactDOM from "react-dom";
import { observable } from "mobx";
import { observer } from "mobx-react";

class Count {
  @observable count = 0;
}

const App = observer(({ store }) => {
  return (
    <div className="App">
      <button
        onClick={() => {
          store.count++;
        }}
      >
        Increment
      </button>
      <button
        onClick={() => {
          store.count--;
        }}
      >
        Decrement
      </button>
      <p>{store.count}</p>
    </div>
  );
});

const store = new Count();
const rootElement = document.getElementById("root");
ReactDOM.render(<App store={store} />, rootElement);

In the code above, we created a store by defining the Count class:

class Count {
  @observable count = 0;
}

Then we create a new instance of the Count class so that we can pass it into our component as a prop by writing:

const store = new Count();

and:

ReactDOM.render(<App store={store} />, rootElement);

Then to define our App function component, we wrap a function around the observer function so that the latest values from the store will be observed.

This means that once we pass in the store , we’ll get the latest values automatically, and when we change the store properties that have the @observable decorator before it, the value will be propagated to the store.

Therefore, in our onClick props, we can pass in a function that changes store.count directly to update the values, which then will immediately be reflected in store.count that we added in the p element.

We can also use the observer decorator with React class component as follows:

import React from "react";
import ReactDOM from "react-dom";
import { observable, computed, autorun } from "mobx";
import { observer } from "mobx-react";

class Person {
  @observable firstName = "Jane";
  @observable lastName = "Smith";
  @computed
  get fullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}

@observer
class App extends React.Component {
  render() {
    const { store } = this.props;
    return (
      <div className="App">
        <p>{store.fullName}</p>
      </div>
    );
  }
}

const store = new Person();
const rootElement = document.getElementById("root");
ReactDOM.render(<App store={store} />, rootElement);

It does the same thing as the observer function with React function components.

Computed Values and Getters

We can create a function in our store class that returns a value that’s computed from other observable values.

To do this, we can use the @computed decorator before our method. We can define one and use it as follows:

import React from "react";
import ReactDOM from "react-dom";
import { observable, computed } from "mobx";
import { observer } from "mobx-react";

class Person {
  @observable firstName = "Jane";
  @observable lastName = "Smith";
  @computed
  get fullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}

const App = observer(({ store }) => {
  return (
    <div className="App">
      <p>{store.fullName}</p>
    </div>
  );
});

const store = new Person();
const rootElement = document.getElementById("root");
ReactDOM.render(<App store={store} />, rootElement);

In the code above, we have a method fullName in the Person class that is a getter and it returns `${this.firstName} ${this.lastName}`, which are the 2 observable properties we defined combined.

Then we can get the fullname property in the store prop as we did in the App component.

Custom Reactions

Custom reactions are created by using the autorun, reaction, or when functions by passing in a callback to them. Reactions are used for committing side effects.

For example, we can create them as follows:

autorun(() => {
  console.log(store.fullName);
});

In the code above, we created a reaction that runs automatically when we run the code.

We log the value of store.fullName from above, and we can use that in our component as follows:

const App = observer(({ store }) => {
  autorun(() => {
    console.log(store.fullName);
  });

  return (
    <div className="App">
      <p>{store.fullName}</p>
    </div>
  );
});

Conclusion

We can use Mobx to create a simple store to store our values. It comes with decorators and functions to get us to watch the values from React components and manipulate the store values directly.

With the observable decorator, we can watch the values from the store and then save change the values directly.

The computed decorator lets us get the functions from getters in the store class in our components.

To commit side effects, we can add custom reactions.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

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