1. Why is state management needed?

In the component

  • The class component state
  • Function component useState

Between components

  • Communication between father and son
  • Communication between parent and grandson passes props twice
  • But any component?

This is where mobx and Mobx-React are used.

2.mobx

The core concept

The document

Mobx Chinese documentation

Basic usage

  • State
import { observable, computed, action, autorun } from "mobx"; //State, observed const todos = (Observable ([{title: "get up ", completed: false}, {title:" dress up ", completed: false}, {title: "get up ", completed: false}, {title:" get up ", completed: false}, {title: "get up ", completed: false}, {title:" get up ")); "Wash ", completed: false}]);Copy the code
  • Computed
//Computed values, triggered by an update to State let uncompletedCount = Computed (() => todos.filter(todo =>! todo.completed).length );Copy the code
  • Reactions
/ / Reactions, Autorun (() => {console.log(' Remaining tasks :${uncompletedCount} ', todos.filter (todo =>! todo.completed) .map(todo => todo.title) .join(", ") ); });Copy the code
  • Actions
const doTask = action(() => { todos.find(todo => ! todo.completed).completed = true }); doTask()Copy the code

A decorator

What is a decorator

  • Core idea: Keep the original name and main function, add one

Some ancillary features

  • A design pattern used to “decorate” a function or object
  • ES7 new syntax for decorating classes or properties

Observable can be used on instance fields and property getters. The @Observable provides fine-grained control over which parts of the object need to be observable.

import { observable, computed } from "mobx"; class OrderLine { @observable price = 0; @observable amount = 1; @computed get total() { return this.price * this.amount; }}Copy the code

Mobx decorator writing

import { observable, autorun, computed, action } from 'mobx'; Class Todo {@Observable todos = [] constructor() {autorun() => {console.log(' Remainder :${this.uncompletedCount} ', this.todos .filter(todo => ! todo.completed) .map(todo => todo.title) .join(", ") ); }); } @computed get uncompletedCount() { return this.todos.filter(todo => ! todo.completed).length; } @action addTodo(title) { this.todos.push({ title: title, completed: false }); } @action doTask(){ this.todos.find(todo => ! todo.completed).completed = true } }Copy the code

core idea

The change of state triggers a series of automatic actions

Decorators are used in the React project

  • yarn eject
  • yarn add @babel/plugin-proposal-decorators
  • Modify package.json, find the Babel field and add “plugins”: [

“@babel/plugin-proposal-decorators” ]“`

3.mobx-react

Use MOBx in the Class component

  • Set up the Store
import { observable, action } from 'mobx';
class AboutStore {
 @observable counter = 1;
 @action add() {
 this.counter++;
 }
}
export default new AboutStore;
Copy the code
  • Provide data sources
import { Provider } from 'mobx-react';
ReactDOM.render(
 <React.StrictMode>
 <Router>
 <Provider homeStore={homeStore} aboutStore={aboutStore}>
 <App />
 </Provider>

 </Router>
 </React.StrictMode>,
 document.getElementById('root')
);
Copy the code
  • Using data sources
import { observer, inject } from 'mobx-react'; @inject('aboutStore') @inject('homeStore') @observer class About extends Component { render() { return ( <div> <h1>About</h1> <p>current counter : {this.props.aboutStore.counter}</p> <p>home counter: {this. Props. HomeStore. Counter} < / p > < Link to = "/" > go home page < / Link > < / div >). }}Copy the code

Use MOBx in function components

  • Set up the Store
import { observable, action, computed } from 'mobx'; export class HomeStore { @observable counter = 1; @computed get doubleCounter() { return this.counter * 2; } @action add() { this.counter++; }}Copy the code
  • Creating a Context object
import React from 'react'; import { HomeStore } from '.. /stores/home'; import { AboutStore } from '.. /stores/about'; export const storesContext = React.createContext({ homeStore: new HomeStore(), aboutStore: new AboutStore() });Copy the code
  • useContext

Set the useStores function to get the Context object within the function component

import React from 'react'; import { storesContext } from '.. /contexts'; export const useStores = () => React.useContext(storesContext);Copy the code
  • Use the context

Look at the component and get the context object through useStore

import React, { Component } from 'react'; import { observer } from 'mobx-react'; import { useStores } from '.. /hooks/use-stores'; const About = observer(() => { const { homeStore, aboutStore } = useStores(); return ( <div> <h1>About</h1> <p>current counter : {aboutStore.counter}</p> <p>home counter: {homeStore.counter}</p> </div> ) }Copy the code

reference

  • Mobx Chinese documentation