preface
React, VUE, and other popular front-end frameworks are also relatively complete. For large-scale projects, reasonable organization of data management is inseparable to the overall quality of the project and development efficiency, such as
- vue: vuex
- React: Redux, MOBx (V4/5, v6), Recoil
I will not compare Redux in detail here. Personally, THERE are several reasons not to choose Redux
- Redux: Redux Hooks already implement React Hooks, useReducer and useContext are not necessary
- Importantly, the Redux data flow mechanism is top-down, inconsistent with the current popular “plug and play” design principles, and has higher development costs than Mobx and Recoil (except umi and DVA, which have some limitations due to higher umi learning and maintenance costs and less flexible DVA).
The overall contrast
- Mobxjs/mobx (6) : github.com/mobxjs/mobx
- Facebook/Recoil: github.com/facebookexp…
Compare the item | mobx | recoil |
---|---|---|
Lot number of Star | 23.1 k. | 11.4 k. |
The React hooks to support | mobx v6 + mobx-react – Mobx is an observable data object tool that can be used in React, Vue, and JS projects – Mobx-react is a tool to associate observables with react |
No additional auxiliary tools, natural support |
UI and logic are decoupled | support – React calls the store action, and the logic is processed in the store |
Does not support – React calls Recoil’s useRecoilState API to implement business logic in components, such as: const [amount, setAmount] = useRecoilState(amountState) |
Singletons versus multiple cases | – export default new Store() is instantiated internally – export default Store, which is instantiated at the reference point Through the program control, more flexible, easy to customize |
Each atom and each selector is a singleton |
Data Flow (single project) | – globalStore => Root => React.FC – pageStore => React.FC |
atom[ => selector] => React.FC |
State induction | The when, reaction | Does not support |
The interaction between the store | support | Does not support |
Number of common apis (PCS) | 5 + | 6 + |
Learning costs | The lower | The lower |
Understand the cost | low | In the |
Development experience | friendly | Average, even troublesome, not suitable for large projects |
Basic service contrast
mobx
- TestStore, for example
import { makeAutoObservable, runInAction } from 'mobx';
class TestStore {
amount = 1; // observable state
data; // observable state
constructor() {
// Automatically listen on all attributes
makeAutoObservable(this);
}
// computed
get price() :string {
return ` $The ${this.amount * 100}`;
}
// action
increment(): void {
this.amount++;
}
/ / async action,
async asyncAction(id: string) :Promise<void> {
try {
const data = await geAsyncData(id);
// In an asynchronous action, the code contains the runInAction(() => {/**... * /})
runInAction(() = > {
this.data = data;
});
} catch (e) {
throw new Error(e); }}}export default new TestStore();
Copy the code
- Use In React: Use mobx-React
import { FC } from 'react';
import { observer } from 'mobx-react';
import store from './testStore';
const Test: FC = () = > {
return (
<div>
<div>count: {store.amount}</div>
<div>price: {store.price}</div>
<button type="button" onClick={()= > store.increment()}>add +1</button>
<button type="button" onClick={()= >Store. AsyncAction (1)}> Async request</button>
</div>
);
};
/ / listening Component
export default observer(Test);
Copy the code
recoil
- Recoil’s data is all particles, paved,
import { atom, selector } from 'recoil';
// state
export const amountState = atom({
key: 'amountState'.default: 0});// computed
export const priceState = selector({
key: 'priceState'.get: ({ get }) = > {
return ` $${get(amountState) * 100}`; ; }});// async state request
export const asyncTestData = selector({
key: 'asyncTestData'.get: async ({ get }) => {
return awaitgeAsyncData(); }});// What's the fuck, if you want async data with params in recoil-store, you must use another API "selectorFamily"
// async state request with params
export const asyncTestDataWithParams = selectorFamily({
key: 'asyncTestDataWithParams'.get: id= > async ({ get }) => {
return awaitgeAsyncData(id); }});Copy the code
- Use In React
import { FC } from 'react'; import { useRecoilState, useRecoilValue } from 'mobx-react'; import { amountState, priceState, asyncTestDataWithParams } from './testStore'; const Test: FC = () => { const [amount, setAmount] = useRecoilState(amountState); const price = useRecoilValue(priceState); const getData = () => { return userRecoilValue(asyncTestDataWithParams(1)); } return ( <div> <div>count: {amount}</div> <div>price: {price}</div> <button type="button" onClick={() => setAmount(amount + 1)}>add +1</button> <button type="button" The onClick = {() = > getData ()} > asynchronous request < / button > < / div >). }; // Monitor Component export default Observer (Test);Copy the code
State induction
- State sensing: When a certain observable data of AStore reaches the condition, it will automatically trigger other actions of the store or trigger actions of other stores. The program description is when(a.isready === true) => B.action().
- The Recoil particle says no such scenario exists
- Mobx supports status-sensing scenarios
class TestStore {
isReady = false;
count = 0;
constructor() {
makeAutoObservable(this);
// listen for isReady, and when isReady becomes true, doSomething (one-time behavior)
when(() = this.isReady, () = > this.doSomething());
// Listen for amount, and output value, previousValue after each amount change
reaction(
() = > this.amount,
(value, previousValue) = > {
console.log(value, previousValue); }); } doReady():void {
this.isReady = true;
}
doSomething(): void{... } increment():void {
this.amount++; }}Copy the code
The interaction between the Store
- Recoil: Not supported
- Mobx: Singleton mode based on store instances, and stores can reference and call each other, and initial control of data flow can be achieved through stores
import stores from './installStores';
class ScheduleStore {
isRunning = false;
constructor() {
makeAutoObservable(this);
}
async run(): Promise<void> {
try {
// User information is initialized
await stores.userStore.init();
await stores.testStore.init();
runInAction(() = > {
this.isRunning = true;
});
} catch (e) {
console.log(e); }}}Copy the code
Store the form
- Mobx: A store as a class, easy to extend functionality: inherit classes, implement interfaces
- Recoli: a single particle store, not extensible, to carry on advanced usage
The end of the
Mobx and Recoil basic comparative analysis has been OK, in short, each has its own characteristics, are very excellent data management tools, in the selection of technology, also need to refer to the actual application scenarios and development costs of the project, I hope this article can help you all.
To learn more about MOBx, read React hooks + Mobx Usage of Summary
reference
- mobx.js.org/
- mobx-react.js.org/
Join us at ❤️
Bytedance Xinfoli team
Nice Leader: Senior technical expert, well-known gold digger columnist, founder of Flutter Chinese community, founder of Flutter Chinese community open source project, well-known developer of Github community, author of dio, FLY, dsBridge and other well-known open source projects
We look forward to your joining us to change our lives with technology!!
Recruitment link: job.toutiao.com/s/JHjRX8B