Ducks: 一种redux的模块组织方式
先前用redux写的项目中每次新增加一个功能都要从actionTypes,actions,reducer一个个文件开始添加,一不小心还会出错,因此在github找了找发现一种名叫ducks的redux代码组织方式。下面就简单介绍下它的思想。
作者遇到的问题跟我的困扰是一样的,每次新增加一个功能就需要在单独的文件中分别添加{actionTypes, actions, reducer}
对,因此把不如将他们都组合放在一个单独的模块中。
方案
例子
下面就是一个组织到一起的名为widgets的module:
// widgets.js
// Actions
const LOAD = 'my-app/widgets/LOAD';
const CREATE = 'my-app/widgets/CREATE';
const UPDATE = 'my-app/widgets/UPDATE';
const REMOVE = 'my-app/widgets/REMOVE';
// Reducer
export default function reducer(state = {}, action = {}) {
switch (action.type) {
// do reducer stuff
default: return state;
}
}
// Action Creators
export function loadWidgets() {
return { type: LOAD };
}
export function createWidget(widget) {
return { type: CREATE, widget };
}
export function updateWidget(widget) {
return { type: UPDATE, widget };
}
export function removeWidget(widget) {
return { type: REMOVE, widget };
}
规则
在module中我们需要遵循下面的代码风格和命名方式:
- 须用
export default
输出名为reducer()
的函数 - 须用
export
输出 函数形式的action creators
- 须用
npm-module-or-app/reducer/ACTION_TYPE
的命名形式来命名action types
,因为到后期很多reducer,不同的人协同工作难免会出现命名重复,这样子加上app和模块的前缀的话就不会出现命名冲突的问题。 - 须用大写的蛇形方式
UPPER_SNAKE_CASE
来命名action types
。
名字
作者把这种模式叫做ducks的原因纯粹就是根据redux最后音节的发音...
用法
最后的用法也并无太大差异。
下面是combineReducers
:
import { combineReducers } from 'redux';
import * as reducers from './ducks/index';
const rootReducer = combineReducers(reducers);
export default rootReducer;
然后是bindActionCreators()
:
import * as widgetActions from './ducks/widgets';
或者有时候需要用枚举的方式:
import {loadWidgets, createWidget, updateWidget, removeWidget} from './ducks/widgets';
// ...
bindActionCreators({loadWidgets, createWidget, updateWidget, removeWidget}, dispatch);
实践
我原来的项目比较大,直接修改还需时间,作者的提供的demo有的也过于庞大有的也比较老了,因此我在基于那个简单的demo做一些更新与修改,后面会继续更新。