2016-02-20 30 views
0

我的我的終極版狀態樹的心智模式看起來是這樣的:如何編寫一個帶嵌套對象狀態減速

{ 
    selectedDepartment: 'Chemistry', 
    purchasesByDepartment: { 
    Chemistry: { 
     purchaseOrders: { 
     ... 
     }, 
     invoices: { 
     ... 
     } 
    }, 
    Biology: { 
     purchaseOrders: { 
     ... 
     }, 
     invoices: { 
     ... 
     } 
    }, 

    ...(another department, etc) 
    } 
} 

這裏是我的減速器

const purchasesByDepartment = (state = {}, action) => { 
    switch (action.type) { 
    case RECEIVE_POS: 
     return Object.assign({}, state, { 
     [action.department]: { 
      purchaseOrders: action.json 
      // but this wipes out my invoices   
     } 
     }) 
    case RECEIVE_INVOICES: 
     return Object.assign({}, state, { 
     [action.department]: {   
      invoices: action.json 
      // but this wipes out my purchaseOrders 
     } 
     }) 

    default: 
     return state 
    } 
} 

可以在每個部門看,我有一個purchaseOrders和一個發票密鑰。 我正在盡我所能寫我的減速器,使它不會改變我的狀態,但我沒有運氣,因爲每個動作當前擦除了另一個鍵。

我啓動了兩項操作:RECEIEVE_POS,RECEIVE_INVOICES。

當我的行動RECEIVE_POS被調度時,我可以用購買訂單創建一個新的狀態,但是這會抹掉我的發票。

當我的行動RECEIVE_INVOICES被調度時,我可以用發票創建一個新的狀態,但是這消除了我的訂單。

如何編寫我的reducer以便我的訂單和發票保持在我的狀態下?

回答

0

對象傳播計算的屬性名稱幫我解決這個問題

case RECEIVE_POS: 
    return { 
    ...state, 
    [action.department]: { 
     ...state[action.department], 
     purchaseOrders: action.json 
    } 
    } 
case RECEIVE_INVOICES: 
    return { 
    ...state, 
    [action.department]: { 
     ...state[action.department], 
     invoices: action.json 
    } 
    } 
2

您可以先應用更改爲部門創建新狀態,然後將其合併到縮減器狀態中。

const purchasesByDepartment = (state = {}, action) => { 
    switch (action.type) { 
    case RECEIVE_POS: 
     let nextPOS = Object.assign({}, state[action.department] || {}, { 
     purchaseOrders: action.json 
     }); 

     return Object.assign({}, state, nextPOS); 
    default: 
     return state 
    } 
} 

個人而言,我喜歡讓我的整個商店一成不變的使用immutablejs使操作這樣的(和一堆其他的東西)簡單:

return state.setIn([action.department, 'purchaseOrders'], action.json]); 
+0

我喜歡這個答案相結合。看起來我需要花一些時間檢查ImmutableJS – Kevin

1

我使用擴運算符(表示爲...arrayName ) 爲了達成這個。這是es6,我用babel啓用了這個功能。

Spread將數組分解爲其元素,因爲它比Object.assign更具人類可讀性。

使用你的背景下,在我的減速器一個簡單的場景,我只是去這樣的:

return { 
    ...state, 
    selectedDepartment: 'Chemistry or whatever' 
} 

這將返回狀態組成的陣列,加上selectedDepartment與給定值覆蓋。

對於嵌入的對象,你可以把它像這樣:

return { 
    ...state, 
    purchasesByDepartment: { 
     ...state.purchasesByDepartment, 
     Chemistry: { 
      ...state.purchasesByDepartment.Chemistry, 
      invoices: { 
       {your new invoices object comes here} 
      } 
     } 
    } 
} 
+0

您的回答給了我一個使用Object spread與計算屬性名稱結合來解決此問題的想法 – Kevin

+0

確實,它看起來不錯。 – Mark