配置
在umi文件夹下有一个.umirc.ts文件,在文件中写入
dva: { immer: true, },
就开启了dva的immer模式
注:如需兼容 IE11,需配置 { immer: { enableES5: true }}。
约定式model的创建
符合以下规则的文件会被认为是 model 文件,
src/models 下的文件
src/pages 下,子目录中 models 目录下的文件
src/pages 下,所有 model.ts 文件
+ src
+ models/a.ts
+ pages
+ foo/models/b.ts
+ bar/model.ts
其中 a.ts,b.ts 和 model.ts 如果其内容是有效 dva model 写法,则会被认为是 model 文件。
model模板
import { Effect, ImmerReducer } from 'umi';
//api为封装的请求
import api from '@/https/api'
//定义类型的接口,ts可用
export interface IndexModelState {
name: string;
baseUrl: string;
}
export interface IndexModelType {
namespace: 'index';
state: IndexModelState;
effects: {
login: Effect;
};
reducers: {
// 启用 immer 之后
save: ImmerReducer<IndexModelState>;
};
}
//实际数据及方法使用
const IndexModel: IndexModelType = {
//namespace是唯一标识,用于快速找到对应的model
namespace: 'index',
//类似vue中的state,用于管理状态,存储共享数据
state: {
name: 'lili',
baseUrl: 'http://localhost:7001'
},
//类似于vuex的action,一般用于管理请求,并将请求结果由下方的reducers来改变state中数据值
effects: {
//方法,一般用来发请求,有两个参数,第一个为传递过来的参数,第二参数对应操作
*login({playLoad}, { call, put }) {
try {
const res = yield call(api.login, { username: 111, password: 222 })
console.log(res)
yield put({ type: 'save', payLoad: { name: '456' } })
} catch (err){
console.log(err)
}
},
//类似vuex mutations
reducers: {
// 启用 immer 之后
save(state, action) {
console.log(action.payLoad.name)
state.baseUrl = action.payLoad.name;
},
},
};
export default IndexModel;
下方有effect中参数详细
组件中实际使用
在组件导入中将useSelector, useDispatch 导入
import React, { useState, useEffect } from 'react'
import {useSelector, useDispatch } from 'umi';
const index = () => {
const dispatch = useDispatch()
//与redux使用方法相似,store为所有的model模块,详细见下图
let name=useSelector(store=>store.index.name)
let change = ()=>{
dispatch({
//page是model的唯一namespace,save是其reducers中方法
type: 'page/save',
//login是effects中方法
//type: 'page/login',
//payLoad用来传递参数,在model中effect的{playLode}和reducers的action中接收
payLoad: {
name: '柠檬啊'
}
})
}
return (
<div>
<button onClick={change}>改变state中的值</button>
</div>
)
}
export default index
store内容
model中使用其他effect方法以及reducers中方法
*login({palyLoad}, { call, put }) {
try {
//api.login为封装的promise请求,palyLoad为请求所需参数
const res = yield call(api.login, palyLoad)
console.log(res)
// 请求成功后,就可以将对应的请求data,通过reducers中方法提交到state中,其中put类似于dispatch
yield put({ type: 'save', payLoad: { name: '456' } })
} catch (err){
console.log(err)
}
},
以这个方法为例,{playLoad}为dispatch提交上来的参数
用res来接收call发出请求的返回值
部分文字来源umi官网 https://umijs.org/zh-CN/plugins/plugin-dva