2016-09-07 85 views
0

当使用redux和react-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

你基本上用另一个对象(你的有效载荷,也是一个对象)替换一个对象(之前的状态)。

在标准的JS来说,这将是你的减速机做什么的equlivalent:

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

辉煌 - 第二选项的工作,谢谢。顺便说一句,我尝试过使用传播运算符,但它一直在抛出语法错误。' - 这是因为它们的实验性质吗?我正在使用webpack和babel来编译我的代码,并且在应用程序的其他部分使用了扩展运算符而没有任何问题,但由于某种原因,在这一部分中它不起作用。任何想法,为什么这是 - ES6语法更好,所以我想尽可能使用它! – Chris

+0

我想这是因为你已经使用了数组传播,这是ES6语法的一部分。对象传播是不同的,目前在阶段2(很不幸,我们将不得不等待它,直到ES2018)。如果你使用的是Babel 6,你需要[Object rest spread plugin](https://babeljs.io/docs/plugins/transform-object-rest-spread/)。 – mdziekon

+0

当然 - 是的,我用过的其他时间是用数组,而不是对象。辉煌,感谢您的帮助! – Chris

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; 
} 
相关问题