preface

In ReactJS, state transfer between parent and sibling components can only be passed through props. If too many variables need to be passed, the project will be chaotic and difficult to maintain, and unexpected bugs will easily occur. So we need a tool to manage global state, such as Redux, Mobx, etc. to solve this problem.

Basic mobx concepts

  • Make state management simple and extensible.
  • State: Is the data that drives the application.
  • Spawn: Something that comes from a state and doesn’t have any further interaction is spawn.
  • Action: is any piece of code that can change state.

Mobx/mobx – react explanation

The main API

  • Observable: Mobx property sets observable status
  • The Action: mobx property defines when the state is updated
  • Compute: the mobx property listens for automatic new values
  • Provider: The Mobx-React property is used to connect to mobx
  • Observer: The Mobx-React property converts the React component to reactive
  • Inject: The Mobx-React property injects mobx defined instances into the React component

The basic configuration

1. Install mobx

NPM install mobx --save NPM install react-mobx --saveCopy the code

2 is directly defined in the React component

import React from "react"; import ReactDOM from "react-dom"; import { observable, action } from "mobx"; import { observer } from "mobx-react"; Let appState = Observable ({timer: 0}); SetInterval (action() => {appstate. timer += 1; }), 2000); appState.resetTimer = action(() => { appState.timer = 0; }); Let TimeView = observer(({appState}) => {return (<div className="App"> <h1>Time: : {appState.timer}</h1> <button onClick={appState.resetTimer}>reset timer</button> </div> ); }); Let TimeView2 = observer(({appState}) => {return (<div className="App"> <h1>Time: {appState.timer}</h1> </div> ); }); Let TimeView3 = ({appState}) => {return (<div className="App"> <h1>Time: {appState.timer}</h1> </div> ); }; let App =()=>{ return ( <div> <TimeView appState={appState} /> <TimeView appState={appState} /> <TimeView3 /> </div> ) }  const root = document.getElementById("root"); ReactDOM.render(<App />, root);Copy the code

Basic API usage examples

Mobx’s core API is divided into four categories: define state (Observable), response state (Autorun, computed), modify state (Action), and auxiliary functions

1.mobx-react

  • Provider: a component in mbox-react that uses the upper and lower parts of react to pass state in the store to child components
// Use the react component as the outermost component of the project <Provider {... store}> <App /> </Provider>Copy the code
  • Observer: Converts a decorator defined by the React component to a responsive component that tracks render and automatic re-render when some observable value changes.
Observable (class Demo extends Component{}); observable(class Demo extends Component{});Copy the code

Note: When the Observer needs to combine other decorators or higher-order components, make sure the Observer is the deepest (first applied) decorator, otherwise it may do nothing.

  • Inject: Inject store into the current component. (Connect components to supplied stores)
Inject ("appStore") @Observer class Demo extends Component{} inject("appStore")(Observable (class Demo) extends Component{}));Copy the code

Use the following steps: 1. Use the Observer to define the observable component. 2. Inject related Stores into components using Inject 4. Use the state defined in Stores

2.mobx

  • Observable: Defines the observable state, with values of either basic or reference types.
// The decorator uses @Observable classProperty = value to create an Observable box that stores observable references to value. The get() // method gets the current value in the box, and the set() method updates the value. observable.box(value, options?)Copy the code
  • Compute: creates the calculated value

Note: Every time a computed value is read, if its dependent state or other computed values have not changed, the last cache result is used to reduce computational overhead. For complex computed values, caching can greatly improve performance.

const ca = computed(() => {
  return 10 * store.a;
});
Copy the code
  • Autorun: Used to define a response function whose type definition is as follows (simplified)
autorun(reaction: () => any): IReactionDisposer;
Copy the code

Computed is similar to Autorun in that it restarts when the dependent state changes. The difference is that computed receives a pure function and returns a calculated value that is updated automatically when the state changes and can be used in Autorun.

const store = observable({ num: 1 }); const totalPrice = computed(() => { return 42 * store.num; }); Autorun (() = > {the console. The log (" quantity * price + ` "${store. Num} * 42 = ${totalPrice. The get ()} `); }); // 1 * 42 = 42 store.num += 1; // 2 * 42 = 84 store.nub += 1;Copy the code
  • Actions: Any application has actions. An action is anything that modifies the state. With MobX you can explicitly mark the location of the action (modify the state) in your code
// Defining the enforceable state can only be enforceActions configure({enforceActions: "always"}); const store = observable({ num: 1 }); const totalPrice = computed(() => { return 42 * store.num; }); Autorun (() = > {the console. The log (" quantity * price + ` "${store. Num} * 42 = ${totalPrice. The get ()} `); }); // 1 * 42 = 42 const increaseNum = action(() => { store.num += 1; }) increaseNum()Copy the code

Decorator configuration

1 Set the project to allow decorators

  • Install the react – app – rewired
npm i react-app-rewired --save
Copy the code
  • Create config – overrides. Js
module.exports = override()
Copy the code
  • Install the customize-cra plug-in
npm i customize-cra
Copy the code
  • The configuration allows the use of decorators
const {addDecoratorsLegacy()} = require("customize-cra")
module.exports = override(addDecoratorsLegacy())
Copy the code

2 Create a Store instance

  • Create a store directory under the SRC directory
  • Create an index.js file in the Store directory
  • If the item is small, handle store directly in index.js, otherwise it can be defined in multiple files
import {observable,action,computed} from 'mobx';

class AppStore{
    @observable list=[]
    @action
    setList(array){
        this.list=array
    }
}
export default new AppStore();
Copy the code

Connect the react

  • Provide works with indject
  • Use provide in the root component
import React, { Component } from 'react'; import ReactDom from 'react-dom'; import Store from "./store"; import {Provider} from "mobx-react" ReactDom.render( <Provider {... Store}> **** </Provider> )Copy the code

Transform components to reactive

  • Creating a Component Importing
import React, { Component } from 'react'; import Store from "./store"; The import {the observer, inject} from "mobx-react" @inject("AppStore") @observer class Test extends Component { render() { return ( <div> </div> ); } } export default Test;Copy the code

Use the state defined in store

// After the injection, the value stored in the store is mounted to the props of the current component, this.props.AppStore....Copy the code

conclusion

Redux was officially recommended for use in react projects. However, I found it too cumbersome to use Redux in small and medium projects, so I used mobx as the state management library. Mobx’s simplicity, ease of use, and scalability make react state design very easy and convenient. In addition, if you want to learn Mobx quickly, just keep in mind its core point: everything that comes from the application state should be automatically acquired.

Note: This article refers to the official Mobx documentation