MobX 4
The principle of
Reference: zhuanlan.zhihu.com/p/25585910
The most critical Mobx function is autoRun
const obj = observable({
a: 1.b: 2}) when a listener attribute is referenced in autoRun (() = > {
console.log(obj.a)
})
obj.b = 3 // Nothing happened
obj.a = 2 // The observe callback is triggered, and the console says: 2
Copy the code
- When a listener property is referenced in autoRun, it is hooked to that property, and when that property changes, the autoRun callback is executed
- Mobx-react with autoRun: Add an autoRun to the component via the @Observer modifier, so that when the component uses some listener attributes, the autoRun will be triggered and the autoRun will be directly rerender when a listener attribute changes
Some API Mobx
-
A response
- observable
import { observable, action } from 'mobx'; Observable can define properties to be observed // Actions can define functions that have side effects, such as changing observable values Copy the code
store.js
import { observable, action } from 'mobx'; class store { @observable count = 0; @action addCount = () = > { this.count ++ } } export default new store() Copy the code
Can also be
import { observable, action } from 'mobx'; class store { @observable count = 0; @action addCount = () = > { this.count ++ } } export default new store() Copy the code
The first one is usually used more often
- computed
Observable computes properties. It recalculates only when the observable property changes
- autorun
The Autorun handles side effects, triggering an Observable when its value changes
observable(() = > console.log(this.count)) Copy the code
-
Change the observables
-
action
-
Asynchronous action: bound, flow
mobx.configure({ enforceActions: true }) // State changes outside of actions are not allowed class Store { @observable count = 0; @action fetchProjects() { setTimeout(() = > { this.count ++ }, 0); }}Copy the code
This. count ++ will return an error because it is not modifying the @Observable variable in the @action function
The solution
- We can write the assignment outside the bound:
mobx.configure({ enforceActions: true }) // State changes outside of actions are not allowed class Store { @observable count = 0; @action fetchProjects() { setTimeout(() = > { this.addCount(1)},0); } @action.bound addCount(num) { this.count += num } } Copy the code
While this is neat and clear, asynchronous processes can be a bit verbose when they are complex
- Used outside the callback function
action
packaging
mobx.configure({ enforceActions: true }) // State changes outside of actions are not allowed class Store { @observable count = 0; @action fetchProjects() { setTimeout( action('Name it whatever you want.'.() = > { this.count }) , 0); } @action fetchProjectsTwo() { setTimeout(() = > { runInAction(() = > this.count++) }, 0); }}Copy the code
The runInAction is the syntactic sugar for action
- async / await
Lexicographically they look like synchronous functions, and it gives the impression that @action applies to the whole function. But that’s not the case, because async/await is just syntactic sugar around promise based procedures. The result is that @Action applies only to the code block until the first await
So in async/await, after the first await, you must use an asynchronous action
@action async fetchProjects() { const { data } = await fetchGithubProjectsSomehow() // a method to get interface data runInAction(() = > this.count = data.count) } Copy the code
- flow
fetchProjects = flow(function * () { // <- note the * sign, this is a generator function! const { data } = yield fetchGithubProjectsSomehow() // use yield instead of await runInAction(() = > this.count = data.count) }) Copy the code
-
-
Tool function
- toJS
Recursively converts an (Observable) object into a javascript structure
- extendObservable
extendObservable(storeName, { age: 353 }); Copy the code