dva通过model的概念来管理一个领域的模型,包含同步更新的state的reducer,处理异步逻辑的effects等。effects异步处理数据之后的数据,最终也是流向到reducer再去更改state。所以,在dva中,这种单向的数据流转,非常清晰。
在使用dva之前,先来搞清楚几个概念:state,reducer,effect,dispatch,action,以及它们之间的关系。
1、state
state是model的状态数据,基本上是需要在业务组件中使用到的那些数据。更改state有个需要注意的地方,为了保证数据变化时候的可控性,每一次变更state都是返回一个全新的对象,而不能使用引用关系并更改state里面的某个值。因此,在reducer的方法中,每一个方法都是通过return的方式,返回一个全新的state对象。
updateStore:(state), action) => {
console.log(action.type) // '${namespance}/updateStore'
return {
...state,
...action.payload
}
}
复制代码
2、reducer
3、effect
4、dispatch
5、action
在umi项目中使用dva的方式如下:
umi创建的项目的src/models目录下,定义一个global.ts文件
global.ts对象export一个对象
// ts ,如果没有引入ts可以忽略
export type GlobalModelState = { projectInfo: Object};
// ts ,如果没有引入ts可以忽略
export type GlobalModelType = {
namespace: 'global';
state: GlobalModelState;
effects: {};
reducers: {};
};
const GlobalModel: GlobalModelType = {
namespace: 'global',
state: {
projectInfo: {}
},
effects: {},
reducers: {
updateStore: (state: any, { payload }: { payload: any }) => {
return {
...state,
...payload
}
}
},
};
复制代码
注:updateStore接受的两个参数,一个是state,代表当前model中的state,另一个参数是action,也就是在业务组件中通过如下方式dispatch方法中的参数,包含一个type,一个payload。updateStore: (state: any, { payload }: { payload: any })此处涉及到了对象结构以及ts的类型定义,如果不是ts,直接updateStore(state, action) =>{} 即可
const mapDispatchToProps = (dispatch: any) => {
return {
updateProjectInfo: (projectInfo: any) => {
dispatch({
type: `${namespace}/updateStore`,
payload: {
projectInfo
}
})
}
}}
复制代码
dva通过connect方法将model跟组件串联起来,使用方式如下:
// 业务组件.jsx
import { connect } from 'dva'
import React, {useState} from 'react'
const xxComp:React.FC = (props) => {
const { dispatch } = props
//
//
const doSomething = ()=> {
dispatch({
type: '${'global'}/updateStore' // 这里的global对应的是你要更新的namespace对应的model
payload: {
projectInfo: '新的projectInfo'
}
})
}
}
export default connect()(xxComp)
复制代码
注:当通过conect将model与组件连接起来后,dispatch会自动注入到该组件的props中。