preface

MobX is a state management library after Redux. It is lighter than Redux. The overall architecture is an observer mode, where the store of state is the observed and the component that uses the store is the observer. MobX can have multiple store objects, and the state used by stores can be changed.

Concept introduction

MobX makes state management simple and extensible with the idea of functional responsive programming, the philosophy behind which is that any data obtained/derived from an application’s state should be obtained/derived automatically. Like Redux, MobX uses one-way data flow: Action changes the state of the application, and the change in state results in an update of the View.

MobX has four concepts: state, computed Value, reaction, and Action. State updates are performed synchronously, meaning that when an action changes state, the new state can be obtained immediately. Computed Value, on the other hand, uses delayed updates, recalculating values only when it is used, and it is automatically reclaimed when components using computed Value are unloaded.

The state mentioned in MobX refers to observable states, because for unobtainable states, their modifications do not automatically have an impact and are meaningless to MobX’s data flow.

The ES. Next decorator syntax is heavily used in MobX and is officially recommended, but the decorator syntax is still experimental, requiring the Babel plugin babel-plugin-transform-decorators-Legacy.

Simple Todos application

These four concepts are briefly introduced through the Todos application. Use class to define an observable state Todo that represents a task:

import { observable } from "mobx";
class Todo {
    id = Math.random();
    @observable title = "";
    @observable finished = false;
}
Copy the code

The @Observable syntax used here is the decorator syntax. You can also use the ES5 syntax to implement the equivalent:

import { extendObservable } from "mobx";
function Todo {
    this.id = Math.random();
    extendObservable(this, {
        title: "".finished: false
    });
}
Copy the code

Todo’s title and Finished properties become observable after being modified by @Observable, and their changes are automatically notified to the observer. The ID is not decorated by @Observable, so it’s just a normal property. A computed value can be created based on observable state. For example, if you need to get the total number of unfinished tasks in TODOS, use @computed to define an unfinishedTodoCount and calculate the total number of unfinished tasks:

import { observable, computed } from "mobx";
class TodoList {
    @observable todos = [];
    @computed get unfinishedTodoCount() {
        return this.todos.filter(todo= > !todo.finished).length;
    }
}
Copy the code

The TodoList property todos is also an observable property. The array contains the Todo instance objects defined earlier. The unfinishedTodoCount is automatically updated (when used) when the number of elements in ToDOS changes or when the FINISHED property of one of the TODO elements changes. In addition to computed Value responding to changes in state, reaction responds to changes in state, but instead of creating a new value, reaction performs logic that has side effects, such as outputting logs and sending requests. Mobx-react provides the @Observer decorator and observer function that encapsulates the React component as reaction and automatically updates the UI component based on state changes. For example, create TodoListView and TodoView components to represent the UI of the application:

import React, { Component } from "react";
import ReactDOM from "react-dom";
import { oberver } from "mobx-react";
import { action } from "mobx";

@observer
class TodoListView extends Component {
  render() {
    return( <div> <ul> {this.props.todoList.map(todo => { <TodoView todo={todo} key={todo.id} />; })} </ul> Tasks left: {this.props.todoList.unfinishedTodoCount} </div> ); } } const TodoView = oberver(({ todo }) => { const handleClick = action(() => todo.finished = ! todo.finished) return ( <li> <input type="checkbox" checked={todo.finished} onClick={handleClick}/> {todo.title} </li> ); }); const store = new TodoList(); ReactDOM.render( <TodoListView todoList={store} />, document.getElementById("root") );Copy the code

TodoListView uses observable data: Todos and Todo.finished (used indirectly through unfinishedTodoCount), so their changes trigger TodoListView updates. In TodoView, handleClick is used to change the todo.finished action. This is used to change the state of the application using mobX.

reference

MobX

React The way to advance