将突变应用于嵌套地图和DRY

时间:2017-02-20 04:30:31

标签: javascript redux immutable.js

我们一直在使用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));

0 个答案:

没有答案