Simplify action attribute update
Under normal circumstances, store
, some of which are updated frequently, and each attribute needs action
function. When there are more attributes that need to be changed, the amount of code store
, Readability will also be reduced. Just like the following code:
class TestStore {
@observable info = {} as IInfo;
@observable list = [] as IList;
@action
setInfo = (value: IInfo) => {
this.info = value;
}
@action
setList = (value: IList) => {
this.list = value;
}
}
Introducing typescript
in keyof
keywords, the above may be action
function reduces to the following:
class TestStore {
@observable info = {} as IInfo;
@observable list = [] as IList;
@action
setValue = <T extends keyof TestStore>(key: T, value: this[T]) => {
this[key] = value;
}
}
Simplify related dependencies between stores
Callback realizes the communication between Stores
For example, after a method in StoreA is executed, a method in StoreB needs to be called
// /stores/StoreA.ts
class StoreA {
@action
methodA = (cb: () => void) => {
// coding...
if (cb) cb();
}
}
// /stores/StoreB.ts
class StoreB {
@action
methodB = () => {
// coding...
}
}
// /stores/index.ts
export default {
storeA: new StoreA(),
storeB: new StoreB(),
}
Page call
// index.tsx
import React from 'react';
import stores from './stores/index.ts';
import Main from './components/Main.tsx';
const Index = () => {
return <Provider {...stores}>
<Main {...props}></Main>
</Provider>
}
// Main.tsx
import React from 'react';
interface IProps {
storeA?: StoreA;
storeB?: StoreB;
}
const Main = (props: IProps) => {
const { storeA, StoreB } = props;
const { methodA } = storeA;
const { methodB } = storeB;
const handleClick = () => {
methodA(methodB);
}
return <span onClick={handleClick}></span>
}
Promise realizes the communication between Stores
// /stores/StoreA.ts
class StoreA {
@action
methodA = () => {
return new Promise((resolve) => {
// coding...
resolve();
})
}
}
Page call
const Main = (props: IProps) => {
const { storeA, StoreB } = props;
const { methodA } = storeA;
const { methodB } = storeB;
const handleClick = () => {
methodA().then(() => {
methodB();
});
}
return <span onClick={handleClick}></span>
}
Scheduling child stores through the root store to achieve communication
Introduce the root-level store, and change the above store organization to the following form:
// /stores/StoreA.ts
class StoreA {
rootStore: RootStore;
constructor(rootStore) {
this.rootStore = rootStore;
}
@action
methodA = () => {
// coding...
this.rootStore.storeB.methodB();
}
}
// /stores/StoreB.ts
class StoreB {
rootStore: RootStore;
constructor(rootStore) {
this.rootStore = rootStore;
}
@action
methodB = () => {
// coding...
}
}
class RootStore {
storeA: StoreA;
storeB: StoreB;
constructor() {
this.storeA = new StoreA(this),
this.storeB = new StoreB(this),
}
}
// /stores/index.ts
export default {
rootStore: new RootStore(),
}
Page call
const Main = (props: IProps) => {
const { storeA, StoreB } = props;
const { methodA } = storeA;
const { methodB } = storeB;
const handleClick = () => {
methodA();
}
return <span onClick={handleClick}></span>
}
Reduce the granularity of the store
The business logic and interactions of some project pages are extremely complicated. If these business logics are stacked in a store, the code amount of the store will be extremely large, as shown in the figure above, the store has thousands of lines of code. This will seriously reduce the readability of the code, and it will even affect the development efficiency of future generations if you continue to iterate.
Of course, we can split the above into multiple stores to solve the problem. This scenario is not what I consider in this section. I want to talk about the following scenario:
If we want to make such a table, and the data structure given by the back end is like this:
Each object in the quote array corresponds to each quote entry
If the data of each quotation item needs to be changed, you need to traverse the quote array to find the corresponding quotation item object, re-assign the value, and just write a function. What if the business logic (validation, value change, etc.) related to the quotation item is particularly large? Then you have to write a lot of functions to implement, these business codes related to quotation items are piled in a store will definitely make the store more bloated.
Surely some students will say, isn't it enough to split this part into a separate store? But the tabular data as a whole, this kind of business split is not easy to achieve, so is there any other way?
Certainly, every quotation item object in mobx is an observable object. We can extract this object and put it in another store. The previous store is just a reference, and the description may not be clear. The above code explains:
// quotation.ts
class Quotation {
@observable quoteId: string = '';
@observable partNum: string = '';
@observable partName: string = '';
constructor(quotation: any) {
Object.assign(this, {...quotation});
}
@action
...
}
// tableStore.ts
class TableStore {
@observable tableData: ITable = [] as ITable;
assemble = (needResults: any, quotations: any) => {
const data: ITable = [];
needResults.forEach(v => {
quotations.forEach(p => {
if (p.demandItemId === v.demandItemId) {
data.push({
need: v,
quote: p.result.map(o => {
return new Quotation(o);
})
})
}
})
})
}
/** 获取报价项次、报价结果 */
@action
fetchTableData = async () => {
Promise.all([fetchNeedResults(), fetchQuotationResults()]).then((res) => {
if (res[0].code === 200 && res[1].code === 200) {
const needResults = res[0].data;
const quotations = res[1].data;
/** 组装表格数据 */
this.tableData = this.assemble(needResults, quotations);
}
});
};
}
Such a design store
the organization can be more flexible control store
particle size, but also good to avoid store
great technology and people operating the same store
scene. For example, in the figure, the "form part" can be split into "requirements part" and "quotation part". When multiple people develop at the same time, each person only needs to be responsible for the style, business logic, and data storage in their own modules. To a certain extent, a closed loop is formed, which is beneficial for every development, and such a way of organizing the code will also enhance the readability and reusability of the code, and facilitate subsequent maintenance.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。