combineReducers解析

由于redux的单一状态原则,只有一个store,但是我们有很多数据,如果全部集中在一个reducer函数中来处理就会非常的难以维护,在项目中我们一般会拆分成很多reducer,然后在创建store的时候,借助combineReducers对这些reducer进行合并,返回一个总的reducer,那么combineReducers是什么意思,他又怎么来用呢?

借助官网的案例:现在有三个action type分别是SET_VISIBILITY_FILTER,ADD_TODO,TOGGLE_TODO那么就需要分别戳action.type进行判断属于哪个,然后分别做处理。

function todoApp(state = initialState, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return Object.assign({}, state, {
        visibilityFilter: action.filter
      })
    case ADD_TODO:
      return Object.assign({}, state, {
        todos: [
          ...state.todos,
          {
            text: action.text,
            completed: false
          }
        ]
      })
    case TOGGLE_TODO:
      return Object.assign({}, state, {
        todos: state.todos.map((todo, index) => {
          if (index === action.index) {
            return Object.assign({}, todo, {
              completed: !todo.completed
            })
          }
          return todo
        })
      })
    default:
      return state
  }
}

但是我们会发现这个代码非常的冗长,根据数据结构其实可以发现可以分成两类,一类是对visibilityFilter来做改变,一个是对todos来做改变,那么我们就可以拆分成两个函数:
一个是处理todos:

function todos(state = [], action) {
  switch (action.type) {
    case ADD_TODO:
      return [
        ...state,
        {
          text: action.text,
          completed: false
        }
      ]
    case TOGGLE_TODO:
      return state.map((todo, index) => {
        if (index === action.index) {
          return Object.assign({}, todo, {
            completed: !todo.completed
          })
        }
        return todo
      })
    default:
      return state
  }
}

一个处理VisibilityFilters:

function visibilityFilter(state = SHOW_ALL, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return action.filter
    default:
      return state
  }
}

那么我们其实可以发现在todos函数中接收到的state是一个数组,在visibilityFilter接收到的state是一个字符串,那么这样就可以对不同的数据用不同的reducer分别做处理,之后合并成一个reducer就可以了:

function todoApp(state = {}, action) {
  return {
    visibilityFilter: visibilityFilter(state.visibilityFilter, action),
    todos: todos(state.todos, action)
  }
}

那么总的reducer就是todoApp,返回一个对象,分别存储了visibilityFilter的值和todos的值,在visibilityFilter函数中传入state.visibilityFilter和action,在todos函数传入state.todos和action。那么在每次dispatch一个对象以后,都会执行todoApp函数,返回一个新的state对象。

那么就可以借助Redux 提供了combineReducers() 工具类来做上面 todoApp 做的事情,这样就能消灭一些样板代码了。

import { combineReducers } from 'redux'

const todoApp = combineReducers({
  visibilityFilter,
  todos
})

export default todoApp

和上面完全等价,也就是说会生成一个state包含visibilityFilter、todos的变量,并且会在初始化和后续更新的时候都用同名函数来进行更新,更新的时候把上次的state对应这个变量的数值传入。
或者如果你想换一个变量名,那么可以:

const reducer = combineReducers({
  a: doSomethingWithA,
  b: processB,
  c: c
})

function reducer(state = {}, action) {
  return {
    a: doSomethingWithA(state.a, action),
    b: processB(state.b, action),
    c: c(state.c, action)
  }
}

两种完全等价。那么这样你之后获取state的数据就得store.getState().a来获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值