1. Write at the front

React Context API mobx, Mobx-React, mobx-React – Lite, mobx-React Context API, mobx-React Context API

2. What is Mobx?

  1. Simple, scalable state management
  2. MobX is a battle tested library that makes state management simple and scalable by transparently applying functional reactive programming (TFRP)

Mobx is a simple, extensible state management library. Is a battle-hardened library that makes state management easy and extensible through transparent functional responsive programming. Mobx is reliable enough to be used in projects.


As shown in the figure above, Mobx invokes Action through the Event event to modify observal State data, triggering computed to update data automatically, and Reactions to changes in State to update views are at the heart of Mobx.

3. Use of Mobx

Mobx is the 6.x version, the use of common API

3.1 the use ofmakeObservable

import {makeObservable,observable,action,computed,autorun,reaction,when} from "mobx";

/ / create a store

const store = makeObservable({

    count:1.

    get double(){return this.count * 2; },

    / / define the action

    increment(){this.count += 1; },

    decrement(){this.count -= 1; },

}, {

    count: observable,// Attributes that require a response

    double: computed,// Calculate attributes

    increment: action,//action

    decrement: action,

});

class MobxDemo {

  handleRefresh(){

    this.container.innerHTML=`

      count: ${store.count}

      double count: ${store.double}

    `
;

  }

  init() {

    this.handleRefresh();

    this.increaseBtn.addEventListener("click",()=>{store.increment(); });

    this.decreaseBtn.addEventListener("click",()=>{store.decrement(); });

    // Autorun is similar to useEffect in React hooks

    // Autorun is called immediately when the Observable response property is updated

    autorun((a)= >{this.handleRefresh(); });

    // Similar to watch observation in Vue

    reaction(

      (a)= >store.count, // Specify the watch count attribute

      (currentVal, oldVal)=>{console.log(`current: ${currentVal}, old: ${oldVal}`); }

    );

    // Conditional response

    when(

      (a)= >store.count < 0.

() = > {console.log("..."); }

    );

  }

}

const mobxDemo = new MobxDemo();

mobxDemo.init();

Copy the code

3.2 the use ofmakeAutoObservable

Than makeObservable makeAutoObservable is much more simplified, no need to manually specify the observables, action, and computed

import {makeAutoObservable,autorun,runInAction} from "mobx";

// Use makeAutoObservable directly

const store = makeAutoObservable({

  count1.

  get double(){return this.count*2; },

  increment(){this.count+=1; },

  decrement(){this.count-=1; },

  // In MobX, both synchronous and asynchronous operations can be placed in an action,

  // It is only the asynchronous operation that needs to put the assignment operation in the runInAction when modifying the property.

  async asyncDecreament() {

    // Simulate Ajax to get data

    const count = await new Promise((resolve) = >{

      setTimeout((a)= >resolve(1), 50);

    });

    // After retrieving the data, place the assignment operation in the runInAction

    runInAction((a)= >{this.count -= count; });

  },

});

Copy the code

3.3 Use pre-6.x decorator writing

import {observable,action,computed} from "mobx";

class Store {

  @observable count=0;

  constructor(){makeObservable(this); }

  @computed get double(){return this.count * 2; }

  @action increment(){this.count++; }

  @action decrement(){this.count--; }

}

const store = new Store();

Copy the code

4. Use of Mox-React-Lite

Mobx-react-lite is the lightweight version of MOBx-React. Mobx-react-lite is included in mobx-react@6. However, if you use mobx-React-Lite only for functional components, you are advised to use the lightweight mobx-React-Lite

4.1 Use of parent ComponentsuseLocalObservableCreate the store

import React,{createContext} from "react";

import {observer,useLocalObservable} from "mobx-react-lite";

import Child1 from "@/component/Child1";

import Child2 from "@/component/Child2";

import Child3 from "@/component/Child3";



export const Context = createContext(null);



const Parent=(a)= >{

  // 'useLocalStore' is deprecated, use 'useLocalObservable' instead.

  const storeContext = useLocalObservable((a)= >({

    count1.

    get double(){return this.count*2; },

    increase(){this.count+=1; },

    decrease(){this.count-=1; },

  }));

  return (

    <Context.Provider value={storeContext}>

      <Child1 />

      <Child2 />

      <Child3 />

    </Context.Provider>


  );

};

export default observer(Parent);

Copy the code

4.2 Sub-component as function component (using Context)

import React, {useContext,useEffect} from "react";

import {observer} from "mobx-react-lite";

import {toJS,reaction,when} from "mobx";

import {Context} from "@/App";

const Child1=(a)= >{

  const store=useContext(Context);

  useEffect((a)= >{

    console.log("store:", toJS(store));

    reaction(

      (a)= >store.count,

      (cur, pre)=>{console.log(`cur: ${cur}, pre: ${pre}`); }

    );

    when(

      (a)= >store.count < 0.

() = > {console.log("..."); }

    );

  }, [store]);

  // [mobx-react-lite] 'useObserver(fn)' is deprecated

  // Use `<Observer>{fn}</Observer>`instead, or wrap the entire component in `observer`

  return(

    <div>

count: {store? .count}|double:{store? .double}

      <button onClick={()= >store.increase()}>increase</button>

      <button onClick={()= >store.decrease()}>decrease</button>

    </div>


  );

};

export default observer(Child1);

Copy the code

4.3 Sub-component as function Component (without Context)

Instead of using Context, use Mox-React. See section 5.3

4.4 Subcomponents are class components

The store is retrieved from the context. Consumer component

import React,{Component} from "react";

import {Observer} from "mobx-react-lite";

import {Context} from "@/App";

class Child3 extends Component {

  render(){

    return(

      <Context.Consumer>

        {(store)=>(

          <div>

            <Observer>{() = ><div>count:{store? .count}</div>}</Observer>

            <button onClick={()= >store.increase()}>increase</button>

            <button onClick={()= >store.decrease()}>decrease</button>

          <div/>

        )}

      </Context.Consumer>

    );

  }

}

export default Child3;

Copy the code

5. Use of Mox-React

5.1 For the parent Componentmobx-reactTo provide theThe Provider componentPass down store

import React from "react";

import {Provider} from "mobx-react";

import {useLocalObservable} from "mobx-react-lite";

import Child1 from "@/component/Child1";

import Child2 from "@/component/Child2";

const Parent=(a)= >{

  // You can also create a store using mobx

  const storeContext = useLocalObservable((a)= >({

    count:1.

    get double(){return this.count*2; },

    increase(){this.count+=1; },

    decrease(){this.count-=1; },

  }));

  return (

    <Provider store={storeContext}>

      <Child1 />

      <Child2 />

    </Provider>


  );

};

export default observer(Parent);

Copy the code

5.2 Subcomponents are class components

import React from "react";

import {observer,inject} from "mobx-react";

@inject("store")

@observer

class Child1 extends React.Component {

  render()(

    <>

count:{store? .count}|double:{store? .double}

      <button onClick={()= >store.increase()}>increase</button>

      <button onClick={()= >store.decrease()}>decrease</button>

    </>


  )

}

export default observer(Child1);

Copy the code

5.3 Sub-components are function components

import React from "react";

import {inject,observer} from "mobx-react";

const Child2=({store}) = >{

  return(

    <>

count:{store? .count}|double:{store? .double}

      <button onClick={()= >store.increase()}>increase</button>

      <button onClick={()= >store.decrease()}>decrease</button>

    </>


  );

};

export default inject("store")(observer(Child2));

Copy the code

6. Reference materials

  1. How does it feel to write Vue for MobX?
  2. Mobx-react – Lite is lightweight state management based on the React Hook API
  3. A preliminary mobx – react – lite
  4. mobx-npm