【问题标题】:How to Update specific slice of redux state in React如何在 React 中更新特定的 redux 状态切片
【发布时间】:2016-09-07 23:10:36
【问题描述】:

在使用 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,或分配给它们的任何其他值。

希望一切都有意义。

干杯!

【问题讨论】:

    标签: javascript reactjs redux react-redux


    【解决方案1】:

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

    就标准 JS 而言,这相当于你的 reducer 所做的:

    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;
    }
    

    【讨论】:

    • 太棒了——第二个选项有效,谢谢。顺便说一句,我尝试使用扩展运算符,但它一直在第一个 . 上抛出语法错误 - 这是因为它们的实验性质吗?我正在使用 webpack 和 babel 转译我的代码,并且在应用程序的其他部分使用扩展运算符没有问题,但由于某种原因,它不起作用。知道为什么会这样 - ES6 语法要好得多,所以我想尽可能使用它!
    • 我认为这是因为您使用了 Array spread,这是 ES6 语法的一部分。对象传播是不同的,目前处于第 2 阶段(所以不幸的是,我们至少要等到 ES2018)。如果你使用 Babel 6,你需要Object rest spread plugin
    • 当然——是的,我使用它的其他时间是数组,而不是对象。太棒了,谢谢你的帮助!
    【解决方案2】:

    如下所示,让您的有效负载对象在动作创建者上保持平坦...

    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;
    }
    

    【讨论】:

      猜你喜欢
      • 2022-01-24
      • 1970-01-01
      • 2020-08-07
      • 2021-10-29
      • 2022-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-15
      相关资源
      最近更新 更多