如何在1键下拆分减速机?

时间:2016-08-31 06:44:11

标签: reactjs redux

我想将一个减速器分成N个,再将1个键组合在一起。

说我有一个初始状态:

const STATE_INITIAL = {
    nested_component: {
        field1: 1,
        field2: 2
    },
    upper_field: 3
}

然后我有一个减速器:

function reducer(state=STATE_INITIAL, action){
    switch(action){
        case ACTION_UPPER_FIELD:
            return ...
        case ACTION_GRID1:
            return ...
        case ACTION_GRID2:
            return ...
        default:
            return state;
    }
}

我为什么要这样做?

我希望有一个可以在整个项目中重复使用的组件。它总是带有它的初始状态,并且它的减速器我想要连接到应用程序的其余部分。

我的解决方案

我能想到的一种方法是为网格操作堆叠case,为其提供state.grid及其自己的初始状态,并将结果与​​state结合起来:

const STATE_INITIAL = {
    nested_component: {},
    upper_field: 3
};


function reducer(state=STATE_INITIAL, action){
    switch(action){
        case ACTION_UPPER_FIELD:
            return ...
        case ACTION_GRID1:
        case ACTION_GRID2:
            return reducerGrid(state.grid, action);
        default:
            return state;
    }
}

const STATE_INITIAL_GRID = {
    field1: 1,
    field2: 2
};

function reducerGrid(state = STATE_INITIAL_GRID, action) {
        switch(action){
            case ACTION_GRID1:
                return ...
            case ACTION_GRID2:
                return ...
            default: 
                return state;
        }
}

是否有标准化方法或我的解决方案是否合适?我不喜欢的事情是default中的reducerGrid现在似乎多余了,我也不满意必须在两个缩减器中重复这些操作。

我的第二个解决方案

function reducer(state=STATE_INITIAL, action){
    const stateGrid = reducerGrid(state.grid, action)
    let stateNew = state;
    if(stateGrid !== state.grid){
        stateNew = {...state, grid: ...stateGrid}
    }

    switch(action){
        case ACTION_UPPER_FIELD:
            return {...stateNew, ... };
        default:
            return stateNew;
    }
}

第三个解决方案

function reducer(state=STATE_INITIAL, action){
    const stateNew = {...state, grid: ...reducerGrid(state.grid, action)};

    switch(action){
        case ACTION_UPPER_FIELD:
            return ...
        default:
            return stateNew;
    }
}

1 个答案:

答案 0 :(得分:1)

我终于找到了一个我满意的解决方案。

使用此方法:

import R from 'ramda';

function splitReducers(reducers, rest) {
    return (state, action) => {
        const reducersPrepared = R.mapObjIndexed((reducer, key) => {
            return reducer(R.defaultTo({}, state)[key], action);
        })(reducers);

        const getUndefinedIfEmpty = R.ifElse(
            R.isEmpty,
            () => undefined,
            R.identity
        );

        const stateWithoutSplitKeys = R.pipe(
            R.omit(R.keys(reducers)),
            getUndefinedIfEmpty
        )(state);

        return R.merge(
            reducersPrepared,
            rest(stateWithoutSplitKeys, action)
        );
    }
}

我可以通过以下方式编写州树:

Ports: splitReducers({
                grid: reducerGrid,
            }, reducer);

这将导致对象分裂:

{
  Ports: {
     grid: {...},
     isSaving: true,
     isVisible: false
  }
}

应用该方法后,root-reducer乍看之下显示更多状态:

export const rootReducer = combineReducers({
    pageAllocation: combineReducers({
        tabNetwork: combineReducers({
            popupNetworkTemplates: reducerPopupNetworkTemplates,
            gridPorts: splitReducers({  //                <----- HERE IT IS
                grid: reducerGridPortsOnly 
            }, reducerPorts),
        }),
        tabStorage: () => ({}),
        activeTab: reducerPortsActiveTab
    }),