我们一直在使用React + Redux + Immutable JS开发SPA。 我们的Redux状态包含17个地图(目前,但它承诺会增长)具有完全相同的结构{page,pages,sortBy,items,...},我们希望避免复制粘贴缩减器(和测试) ,这是一个简单的例子:
state = fromJS({
pageA: {
tableA1: {loading:..., page:...., pages:..., items:...},
tableA2: {loading:..., page:...., pages:..., items:...}
},
pageB: {
tableB1: {loading:..., page:...., pages:..., items:...},
tableB2: {loading:..., page:...., pages:..., items:...}
}
});
// reducers:
setLoadingTableA1 = state => state.setIn(['pageA', 'tableA1', 'loading'], true);
setLoadingTableA2 = state => state.setIn(['pageA', 'tableA2', 'loading'], true);
setLoadingTableB1 = state => state.setIn(['pageB', 'tableB1', 'loading'], true);
setLoadingTableB2 = state => state.setIn(['pageB', 'tableB2', 'loading'], true);
显然,所有四个减速器都可以用可重复使用的减速器替换,例如:
composeSetLoading = selector => state => selector(state).set('loading', true);
用法:
selectPageATable1 = state => state.getIn(['pageA', 'tableA1']);
// ^^^ It works only for mapping data from state to props
// Unfortunately, it can't be used for composing reducers
setLoadingTableA1 = composeSetLoading(selectPageATable1);
其他好处:composeSetLoading
需要进行一次测试。 setLoadingTableA1
也可以在@connect
重复使用:
@connect(state => ({loading : selectPageATable1(state).get('loading')}))
class TableA1 extends React.Component {...}
有可能实现吗?我很感激任何建议/想法。
更新我:
我知道Map.updateIn(..., updater);
,它有所不同。它允许移出state => state.set('loadding', true)
,但我们正在寻找一种方法来搬出selector
更新II:
我不幸地尝试使用Map.updateIn(..., updater);
,这不够好,因为updater
应该在大多数情况下提供旧状态和一些数据...所以唯一的方法是创建一个新函数每一次:
setItemsTableA1 = (state, items) => state.updateIn(['pageA','tableA1'], state => state.set('items', items));