2016-09-07 91 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; 
} 
相關問題