Redux 进阶:拆分 reducer

❓ state 过于庞大怎么办

因为 Redux 应用中只有一个 store,因此,当应用的交互越来越复杂时,store 必定会变成一个非常庞大的对象。这时,我们可以使用 Redux 提供的 combineReducers() 方法将多个小的 reducer 组合成一个 rootReducer,而每个小的 reducer 只关心自己负责的 action.type,因为在整个应用中,有些 state 之间是互不关联的,因此我们可以拆分 reducer,不同的 reducer 处理不同的 action.type

假设现在有两个逻辑:一个计数器和一个 TODO。很明显这两个逻辑之间没有任何的联系,因此我们可以拆分成两个 reducer,然后再组合起来传给 createStore()

// 计数器 reducer
function counter(state = 0, action) {
  switch(action.type) {
    case 'INCREMENT':
      return state + 1;
    case 'DECREMENT':
      return state -1;
    default:
      return state;
  }
}

// TODO reducer
function todos(state = [], action) {
  switch(action.type) {
    case 'ADD_TODO':
      return state.concat([action.text]);
    default :
      return state;
  }
}

// 组合成一个 rootReducer
const rootReducer = combineReducers({
  counter,
  todos
});

// 根据 rootReducer 创建 store
const store = createStore(rootReducer)

console.log(store.getState());

结果

Redux 进阶:拆分 reducer

可以看到,store.getState() 中的 key 变成了子 reducer 的函数名,达到了拆分之间没有联系的 state 的目的。而 key 变成了子 reducer 的函数名的原因是,在组合 reducer 时的写法:

// 组合成一个 rootReducer
const rootReducer = combineReducers({
  counter,
  todos
});

这里传入给 combineReducers() 方法的是一个对象,这里使用了 ES6 的语法,即当对象的 keyvalue 同名时,可以省略 key,上面的写法相当于:

const rootReducer = combineReducers({
-  counter,
+  counter: counter,
-  todos
+  todos: todos
});

当然,key 是可以随意修改的,只是修改后,对于 state 的 key 也会有所不同罢了。需要记住的是 combineReducers() 方法的参数是一个对象,对象的 value 是需要组合的 reducer,对象的key 对应的是 state 中的 key,返回的是一个组合后的 reducer 函数,可以像普通 reducer 一样传给 createStore() 方法创建 store。

与 React 结合后结果是这样的:

Redux 进阶:拆分 reducer

在 coding 之前

构建一个 Redux 应用之前,我们应该先搭建好架构,也就是设计模式的那一套东西,在 coding 之前,不妨先停下来思考一下:

  • 代码文件的组织结构

    • 按角色组织
    • 按功能组织
  • state 树的设计

    • 一个模块控制一个 state 节点
    • 避免冗余数据:做到 state 的范式化,类似 SQL 关系型数据库。为解决范式化数据的性能问题,可以使用 reselect 这样的工具提高性能。
    • 树形结构扁平,避免很深的层次
  • 确定模块的边界:在理想情况下,我们应该通过增加代码就能增加功能,而不是修改现有的代码。

下面是一个按功能组织的文件结构:

todoList/
  action.js            # 定义 action creators
  actionTypes.js       # 定义 action 类型
  index.js             # 把这个功能模块的文件导入,然后统一导出
  reducer.js           # 定义 reducer 如何处理 action
  views/               # 定义所有 React 组件,包括容器组件和展示组件
    component.js
    container.js
filter/
  action.js
  actionTypes.js
  index.js
  reducer.js
  views/
    component.js
    container.js

相关推荐