A quick introduction to Mobx

MobX is transparent, function-responsive programming, and its main advantages make state management easy and extensible (I’ll compare this briefly with Redux next);

Website sent

Redux vs. Mobx

Both are state management libraries, which are used to manage the internal state of the application, so in our project, they can be completely replaced by each other. Let me simply compare the development cost:

Here I compare with standard project practices, using the Redux library in our daily project development. The following figure shows the directory structure of one of our business components

Instead, let’s look at the mobx file directory structure after refactoring

Specific implementation, below will be introduced in detail, the above only do a simple comparison!

Start building the Mobx project

Better_man: WebPack 4. X: WebPack 4. Better_man: WebPack 4.

Now all we need is Mobx. Let’s start our mobx journey

Step 1: Install the dependency files

npm i mobx mobx-react -D
Copy the code

Step 2: Component and module division

It is important to define the directory structure and module split, so that we can think clearly in the development process, clean code;

Step 3: Divide domain stores and define observable states

We create the moviestore.js file under the Store folder, as shown below

Next, to define the observable state, let’s look at the code:

import {observable, action, computed, runInAction} from 'mobx';
import Api from '.. /api/movie';

export class movieStore {
    @observable movieList = [];
    @observable state = 'pending';

    constructor(rootStore) {
        this.rootStore = rootStore;
        this.fetchMovies = this.fetchMovies.bind(this);
        this.setPrice = this.setPrice.bind(this);
    }


    @action
    async fetchMovies() {
        this.state = 'pending'; this.movieList = []; try { const subjects = await Api.getMovie(); //await after changing the status runInAction(() => {this.state ='Done';
                this.movieList = subjects;
            });
        } catch (e) {
            runInAction(() => {
                this.state = "error"; }); }}}Copy the code

MovieList: movieList and state: request state of the interface. Add @observable in front of its variable to make it observable. Define action to request the interface and change the initial state

npm i babel-plugin-transform-decorators-legacy -D
Copy the code

(2).babelrc file add configuration

"plugins": ["transform-decorators-legacy"]
Copy the code

Step 4: Create views to respond to changes in state

First, in the Views directory, create a new movie file to store the related files of the Movie component, create index.jsx in the Movie folder, and define the advanced components of the React component wrapped in observer

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

@observer
export default class Movie extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
            <div>movie</div>
        )
    }
}
Copy the code

Step 5: Register globally and inject the Store instance

One frequently asked question is how to combine multiple stores without using singletons. How do they communicate with each other? The answer is to create a RootStore to instantiate all stores and share references; Example: the store/index. Js

import {configure, observable, computed} from 'mobx';
import {movieStore} from './movieStore';
import {loginStore} from './loginStore';

configure({enforceActions: 'observed'});

export default class store {
    @observable movieStore;
    @observable loginStore;

    constructor() { this.movieStore = new movieStore(this); this.loginStore = new loginStore(this); }}Copy the code

Complete the combination of multiple domain stores, using

<Provider rootStore={new RootStore()}><App /></Provider>
Copy the code

Into the component library. The next step is to introduce a single store in our view component, switch the perspective back to the Movie component again, and complete the code:

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

@inject((stores) => {
    return {
        movieStore: stores.store.movieStore
    }
})

@observer
export default class Movie extends Component {
    constructor(props) {
        super(props);
    }

    async componentDidMount(){
        const {movieList,fetchMovies} = this.props.movieStore;
        if (movieList.length > 0)
            return;
        await fetchMovies();
    }

    render() {
        const {state, movieList, setPrice, price} = this.props.movieStore;

        const columns = [{
            title: 'name',
            dataIndex: 'title',
            render: text => <a href="javascript:;">{text}</a>,
        }, {
            title: 'Douban Rating',
            dataIndex: 'rating',
        }, {
            title: 'year',
            dataIndex: 'year',
        }, {
            title: 'description',
            dataIndex: 'original_title'
        }];

        const data = movieList.map(item => ({
            id: item.id,
            key: item.id,
            title: item.title,
            rating: item.rating.average,
            year: item.year,
            original_title: item.original_title
        }));

        return (
            <div>
                <Table loading={state === 'pending'} columns={columns} dataSource={data} />
            </div>
        )
    }
}
Copy the code

Inject the store we need by @inject, after which we can access observable properties and methods in the component props; Here I use the TABLE component of ANTD UI library as data display. If you are interested, please go to Ant Design official website

conclusion

Mobx is a mobx project built by mobx and mobx is a mobx project built by Mobx. Mobx is a mobx project built by Mobx and mobx is a mobx project built by Mobx. Mobx is a MOBx project built by Mobx and MOBx is a MOBx project built by Mobx.