在项目中接入dva
1. 创建一个models文件夹,并在内创建一个ts文件models/dep.ts
export default {
namespace: 'dep',
state: {
depList: [],
},
effects: {
*getDep({payload}, {put, call}) {
const data = yield call(setTimeout);
yield put({
type: 'updateState',
payload: {depList: data},
});
},
},
reducers: {
updateState(state, {payload}) {
return {...state, ...payload};
},
},
};
2. 在models内创建index.ts文件models/index.ts
将所有的model导出
import dep from './dep';
import dep1 from './dep1';
export default [dep, dep1];
3. 创建一个dva配置文件 dva.ts
,初始化dva配置
import {create} from 'dva-core';
import immer from 'dva-immer';
let app: any;
const createApp = (opt: any) => {
app = create(opt);
app.use(immer());
if (!(global as any).registered) {
opt.models.forEach((model: any) => {
app.model(model);
});
}
(global as any).registered = true;
app.start();
const store = app._store;
app.getStore = () => store;
const dispatch = store.dispatch;
app.dispatch = dispatch;
return app;
};
export default {
createApp,
getDispatch() {
return app.dispatch;
},
};
4. 导入第2步的models,完成dva初始化
import dvaCore from './dva';
import models from '../models';
const dva = dvaCore.createApp({
initialState: {},
models: models,
});
const store = dva.getStore();
export default store;
5. 在app根目录包裹所有组件
import { Provider } from 'react-redux';
import store from './store';
return <Provider store={store}>
{children}
</Provider>
符合以下规则的文件会被认为是 model 文件,
src/models 下的文件
src/pages 下,子目录中 models 目录下的文件
src/pages 下,所有 model.ts 文件(不区分任何字母大小写)
src
models/a.ts
pages
foo/models/b.ts
bar/model.ts
dva配置
dva: {
immer: true,
hmr: false,
}
skipModelValidate
- Type: boolean
是否跳过 model 验证。
extraModels
- Type: string[]
配置额外到 dva model。
immer
- Type: boolean | object
表示是否启用 immer 以方便修改 reducer。
如需兼容 IE11,需配置{ immer: { enableES5: true }}
。
hmr
- Type: boolean
表示是否启用 dva model 的热更新。
lazyLoad
- Type: boolean
懒加载 dva models,如果项目里 models 依赖了 import from umi 导出模块,建议开启,避免循环依赖导致模块 undefined 问题。
umi常用接口
connect
绑定数据到组件。
getDvaApp
获取 dva 实例
useDispatch
hooks 的方式获取 dispatch
useSelector
hooks 的方式获取部分数据
useStore
hooks 的方式获取 store
model 用例
import type { Effect, ImmerReducer, Reducer, Subscription } from 'umi';
export interface HomeModelState {
name: string,
age: number,
}
export interface HomeModelType {
namespace: 'home';
dva: {
immer: true,
hmr: false,
lazyLoad: true,
},
effects: {
query: Effect;
};
state: HomeModelState;
reducers: {
// 启用 immer 之后
save: ImmerReducer<HomeModelState>;
// 未启用 immer
setData: Reducer<HomeModelState>;
};
subscriptions: { setup: Subscription };
}
const HomeModel: HomeModelType = {
namespace: 'home',
state: {
name: 'code',
age: 19
},
effects: {
*query({ payload }, { call, put }) { },
},
reducers: {
save(state, action) {
state.name = action.payload;
// 注意,此处一定要返回新的state
return state;
},
setData(state, action) {
return {...state, ...action.payload};
}
},
subscriptions: {
setup({ dispatch, history }) {
return history.listen(({ pathname }) => {
if (pathname === '/') {
dispatch({
type: 'query',
});
}
});
},
},
dva: {
immer: true,
hmr: false,
lazyLoad: true,
}
};
export default HomeModel;
page用例
通过useSelector, useDispatch的方式使用state数据
import { useSelector, useDispatch } from 'dva';
const dispatch = useDispatch();
const {name}: any = useSelector(state => state.home);
console.log(name);
useEffect(() => {
dispatch({
type: 'home/save',
payload: {name: '开心就好'},
})
}, [])