记录ant design pro(umi搭建)项目中使用dva
1.启用
umi内置dva,其内部包依赖dva,就会默认下载@umijs/plugin-dva.
dva 通过 model 的概念把一个领域的模型管理起来,包含同步更新 state 的 reducers,处理异步逻辑的 effects,订阅数据源的 subscriptions
2.按规则创建models,其内部文件才会被应用起来
src/models
下的文件src/pages
下,子目录中 models 目录下的文件src/pages
下,所有 model.ts 文件(不区分任何字母大小写)
models文件夹下的文件如果不指定namespace,文件名即 namespace
3.配置dva
export default {
dva: {
immer: true, // 启用immer以方便修改reducer
hmr: false, // 热更新
},
};
4.页面使用
import { connect } from 'umi';
const Index: React.FC = ({ card, dispatch }: any) => {
// 通过namespace取state
const { option } = card;
useEffect(() => {
// 派发action进行切割
dispatch({
type: 'card/addSplit', // 因为有多个namespace
payload: [
{
start: 0,
end: 0,
},
],
});
});
useEffect(() => {
// 派发action进行初始化
dispatch({ type: 'card/init' });
}, []);
return (
<>
<div>{JSON.stringify(option)}</div>
</>
);
};
// 将state应用到DOM上
export default connect((states: any) => ({
...states,
}))(Index);
5.model用例
import { Effect, ImmerReducer, Reducer, Subscription } from 'umi';
export interface IndexModelState {
name: string;
}
export interface IndexModelType {
namespace: 'card';
state: IndexModelState;
effects: {
query: Effect;
};
reducers: {
save: Reducer<IndexModelState>;
// save: ImmerReducer<IndexModelState>;
};
subscriptions: { setup: Subscription };
}
// 异步请求接口
const request = () => {
return new Promise<any>(async (resolve, reject) => {
// resolve(await cardInit());
});
};
const IndexModel: IndexModelType = {
namespace: 'card', // 派发action时,格式: card/xxx
// 默认state
state: {
name: '',
},
// 同步操作state
reducers: {
save(state, action) {
return {
...state,
...action.payload,
};
},
// 启用 immer 之后
// save(state, action) {
// state.name = action.payload;
// },
},
// 异步操作state
effects: {
// *和yield就相当于async/await的底层实现
*query({ payload }, { call, put, select }: any) {
// put可以进行dispatch(触发action)
// call用来请求接口(支持promise)
// select获取所有的state
yield put({ type: 'save', payload: {} }); // type不需要加namespace
let res = yield call(requset);
// 加一些处理逻辑
let states = yield select();
},
},
subscriptions: {
// 进入/users页面,触发action`users/fetch`
setup({ dispatch, history }) {
history.listen(({ pathname }) => {
if (pathname === '/users') {
dispatch({
type: 'users/fetch',
});
}
});
},
},
};
export default IndexModel;
注意: reducers和effects的函数名不能重复
大致理解: 使用connect将view与store进行连接之后,可以获取每个namespace下的state进行使用.
需要同步操作state时,使用dispatch({type: 'namespace/xxx', payload: xxx}).
异步操作也使用dispatch({type: 'namespace/xxx', payload: xxx}),内部修改state时,要进行同步操作.也就是执行put({type: 'namespace/xxx', payload: xxx})