使用前了解
dva的作用和redux的作用一样,在umi的项目中都是使用dva来管理状态的,,dva也是基于react-redux和reudx基础上做了进一步封装的,然后语法有点像vuex,因此会react-redux和vuex的小伙伴学起来很快。
核心概念model
首先先带你了解dva中的核心,model的使用,作用是reducer和action的结合。dva官网可能有些地方没说明清除,我这里讲解的比较详细,看完下面代码,你对dva的model也算是基本掌握了。
export default{
namespace: 'list',
state: [], // model管理的全局状态
reducers: { // 唯一可以修改 state 的地方,触发时机是dispatch
add(state, { payload}) {
return [...state,payload] //返回值为更新的状态
},
},
effects: { // 用于处理异步操作和业务逻辑,触发时机是dispatch
// *相当于async,yield相当于await
*save({ payload: todo }, { put,call,select}) {
// select 的参数是一个函数,函数接收的参数是所有model的状态,该条语句的接收值是函数的返回值
const mystate= yield select(store=>store.todo)
// getListReq需要返回promise,options是getListReq的入参
const res= yield call(getListReq,options);
// put和dispatch一样
yield put({ type: 'add', payload: res.list });
},
},
subscriptions: { // 该选项中的函数自定义命名?函数的触发时机是初始时,主要用来初始化模块状态或者做一些准备性工作
// 注意:subscription 需要返回 unlisten 方法,用于取消数据订阅。
setup({ history, dispatch }) {
//初始化模块状态
dispatch({type:'initList',payload:Json.parse(localStorage.getItem('umi_list'))})
// 监听 history 变化,当进入 `/` 时触发 `load` action
return history.listen(({ pathname }) => { // history.listen监听方法返回 unlisten
if (pathname === '/') {
dispatch({ type: 'load' });
}
});
},
},
}
在umi中使用dva
umi项目中已经帮我们注册好了插件plugin-dva,对dva进行了一个整合,因此在umi项目中,我们使用dva是很方便的。
在umi项目中符合以下规则的文件会被认为是 model 文件。
src/models
下的文件src/pages
下,子目录中 models 目录下的文件src/pages
下,子目录中的model.js | model.ts
像这个list.js文件就是一个model。
umi里面有很多hook,我们可以不需要connect组件,直接使用hook去使用model状态即可,使用方法如下。
import {useDispatch,getDvaApp,useSelector,useStore} from "umi"
export default () => {
const dispatch=useDispatch() // 获取dispatch
const storeState=useSelector(s=>s) // 获取所有model的状态
// const dva=getDvaApp() // 获取dva实例
// const store=useStore() // 获取store对象
const add=(user)=>{
// dispatch({type:'list/add',payload:{name:'a',age:18}})
dispatch({type:'list/add',payload:user})
}
return (
<div>
<button onClick={add}>add</button>
<ul>
{
// model的文件名或者namespce值为总状态的key
storeState.list.map((v)=><li></li>)
}
</ul>
</div>
);
}
也可以使用connect的方式来使用model的状态,看个人喜好吧。
import {connect} from "umi"
const page=(props) => {
const add=()=>{
// props.dispatch({type:'list/add',payload:{name:'a'}})
props.dispatch({type:'list/add',payload:user})
}
return (
<div>
<button onClick={add}>add</button>
<ul>
{
// model的文件名或者namespce值为总状态的key
props.list.map((v)=><li></li>)
}
</ul>
</div>
);
}
export default connect(s=>s)(page)