如何在React中更新特定的redux状态切片

时间:2016-09-07 23:10:36

标签: javascript reactjs redux react-redux

在使用redux和react-redux更新状态时,我似乎遇到了麻烦。当我更新单个状态切片时,所有其他切片都会被删除。我知道这个问题的答案很简单,但我无法弄明白,也无法在网上找到其他任何东西。

所以要澄清一下,这是我的减速机:

const initialState = {
        selectedLevel: null,
        selectedVenue: null,
        selectedUnitNumber: null,
        selectedUnitName: null,
        selectedYear: null
}

export default (state = initialState, action) => {
    console.log('reducer: ', action);
    switch (action.type){
        case 'CHOOSE_LEVEL':
            return action.payload;
        case 'CHOOSE_VENUE':
            return action.payload;
        case 'CHOOSE_UNIT':
            return action.payload;
        case 'SHOW_COURSES':
            return action.payload;
    }

    return state;
}

我的联合减速机:

export default combineReducers({
    workshopSelection: WorkshopSelectReducer
});

所以我的初始状态如下:

workshopSelection: {
    selectedLevel: null,
    selectedVenue: null,
    selectedUnitNumber: null,
    selectedUnitName: null,
    selectedYear: null
}

但是当我使用我的一个动作创建者时,例如:

export function chooseVenue(venue){
    return {
        type: 'CHOOSE_VENUE',
        payload: {
            selectedVenue: venue
        }
    }
}

我的状态看起来像这样:

workshopSelection: {
    selectedVenue: 'London',
}

此对象中未受此动作创建者影响的所有其他状态都已完全消失。相反,我只是希望所有其他条目保持原样值 - 在此示例中为null,或者已为其分配任何其他值。

希望一切都有意义。

干杯!

2 个答案:

答案 0 :(得分:2)

您基本上将一个对象(以前的状态)替换为另一个对象(您的有效负载,也是一个对象)。

就标准JS而言,这将是你的减速器所做的事情的等效性:

var action = {
    type: 'CHOOSE_VENUE',
    payload: {
        selectedVenue: venue
    }
};

var state = action.payload;

解决此问题的最简单方法是使用Object spread properties

export default (state = initialState, action) => {
    switch (action.type){
        case 'CHOOSE_LEVEL':
        case 'CHOOSE_VENUE':
        case 'CHOOSE_UNIT':
        case 'SHOW_COURSES':
            // Watch out, fall-through used here
            return {
                ...state,

                ...action.payload
            };
    }

    return state;
}

...但由于这仍处于试验阶段,您必须使用其他方法克隆以前的属性,然后覆盖新属性。双for ... in循环可能很简单:

export default (state = initialState, action) => {
    switch (action.type){
        case 'CHOOSE_LEVEL':
        case 'CHOOSE_VENUE':
        case 'CHOOSE_UNIT':
        case 'SHOW_COURSES':
            // Watch out, fall-through used here
            const newState = {};

            // Note: No key-checks in this example
            for (let key in state) {
                newState[key] = state[key];
            }
            for (let key in action.payload) {
                newState[key] = action.payload[key];
            }

            return newState;
    }

    return state;
}

答案 1 :(得分:0)

将您的有效负载对象保持为动作创建者的平面,如下所示...

export function chooseVenue(venue){
    return {
        type: 'CHOOSE_VENUE',
        selectedVenue: venue
    }
}

并修改您的减速器如下(给出示例用于更新场地,对其他情况也一样;)

export default (state = initialState, action) => {
    let newState = Object.assign({}, state); // Take copy of the old state
    switch (action.type){
        case 'CHOOSE_LEVEL':
        case 'CHOOSE_VENUE':
               newState.selectedVenue = action.selectedVenue; // mutate the newState with payload
               break;
        case 'CHOOSE_UNIT':
        case 'SHOW_COURSES':
        default :
           return newState;   
    }

    return newState; // Returns the newState;
}