redux入门 互动版

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装置。

Pure_functions

c、执行有副作用的操作,如路由跳转

d、在 default 情况下返回旧的 state。遇到未知的 action 时,一定要返回旧的 state。

完成reducer的添加任务部分