reducer
本小节将介绍一个reducer的创建
1、reducer作用
我们一直强调state只读,而reducer是唯一更新state的途径,通过触发dispatch(后面我们会学到,dispatch可以看成是实例化的reducer)更新state。
2、开发reducer
我们可以先尝试着去开发一个reducer
在创建action的时候我们就知道,我们有三个action
A、添加任务
我们通过更新todos数组,添加任务。
B、完成任务
我们通过改变todos数组中对应任务的complete状态来实现
C、选择需要显示的任务
通过更新filter实现
可能在这个过程中你会对一些用法感到疑惑,为什么我要这样用?我可以有更好更方便的方法可以用啊。
function todoApp(state = initState,action){
switch(action.type){
//改变state的filter,现实现实全部、完成、未完成的选择
case SETFILTER: return Object.assign({},state,
{filter:action.filter}
);
//添加todo
case ADD_TODO: return Object.assign({},state,
{
todos:[...state.todos,{
text:action.text,
complete:false
}]
}
);
//将对应index的任务变为完成状态
case COMPELETE_TODO:return Object.assign({},state,{
todos:return [
...state.slice(0, parseInt(action.index)),
Object.assign({}, state[action.index], {
completed: true
}),
...state.slice(parseInt(action.index)+ 1)
];
}
);
default:
return state;
}
}
3、 reducer设计原则
大家有没有想过,我为啥一定要用assign函数,写得又长又难看,要更新todos直接push不就得了...
必须注意reducer设计是要遵循一定原则的,在第一章我们就强调过了三大原则,在这里我们就必须遵循使用纯函数来执行这条原则。
A、reducer必须是个纯函数
B、永远不要再reducer做这些操作
a、修改传入的参数
像下面这种写法:
function todoApp(state = initState,action){
switch(action.type){
case SETFILTER:
return:state.todos.push({
text:action.text,
complete:false
});
default:
return state;
}
b、调用非纯函数
什么是纯函数?
- 给出同样的参数返回都返回与之对应相同的结果,结果不依赖任何隐藏信息、执行将改变状态的程序的执行,也不能依赖任何外部i/o的输入。
- 结果值不会产生任何语义上可观察的副作用或输出,例如或输出到I/O装置。
c、执行有副作用的操作,如路由跳转
d、在 default 情况下返回旧的 state。遇到未知的 action 时,一定要返回旧的 state。
完成reducer的添加任务部分