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?
- Simple, scalable state management
- 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({
count: 1.
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 ComponentsuseLocalObservable
Create 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)= >({
count: 1.
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-react
To provide theThe Provider component
Pass 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
- How does it feel to write Vue for MobX?
- Mobx-react – Lite is lightweight state management based on the React Hook API
- A preliminary mobx – react – lite
- mobx-npm