2016-03-11 92 views
21

我試圖圍繞如何在redux中改變深層嵌套狀態。對我來說,合併減速器和改變這些部件的第一級屬性是很有意義的。我不太清楚的地方在於如何改變深度嵌套屬性的狀態。 讓我們假裝我有一個購物車應用程序。下面是我的狀態:Redux減速器 - 改變深層嵌套狀態

{ 
    cart: { 
     items: [] 
    }, 
    account: { 
     amountLeft: 100, 
     discounts: { 
     redeemed: [], 
     coupons: { 
      buyOneGetOne: false 
     } 
     } 
    } 
} 

當用戶在代碼進入,讓我們說,他們可以贖回「buyOneGetOne」優惠券和價值應該成爲現實。 我有一個減速器的購物車和另一個帳戶。對於第一級屬性(比如,如果我是清除車的項目),我只想做我減速了以下內容:

case 'EMPTY_CART': 
    return Object.assign({}, state, {items: []}); 

對於改變buyOneGetOne,但是,好像我首先需要做的Object.assign優惠券(因爲buyOneGetOne被修改),然後對摺扣進行Object.assign(因爲我修改了優惠券),然後最終發佈操作,因此reducer可以在帳戶上執行Object.assign(因爲折扣現在改變)。這似乎很複雜,很容易做錯,但是,這使我相信必須有更好的方法。

我對這一切都錯了嗎?看起來減縮器只用於修改狀態的根級屬性(如購物車和賬戶),並且我不應該有一個觸及賬戶內部狀態的減速器(如減價器),因爲賬戶已經有減速器。但是,當我只想在狀態樹上更改一個屬性時,將每個對象從該對象鏈上的所有對象合併到對象鏈的子對象變得複雜...

您可以/您應該嗎?減速機內部有減速機,就像本例中有減速機一樣?

回答

25

你可以確定減速器內有減速器;實際上,Redux演示應用程序執行此操作:http://redux.js.org/docs/basics/Reducers.html

例如,您可以創建一個名爲'折扣巢式減速機:

function discounts(state, action) { 
    switch (action.type) { 
     case ADD_DISCOUNT: 
      return state.concat([action.payload]); 

     // etc etc 
    } 
} 

然後利用這個減速的帳戶中的減速器:

function account(state, action) { 
    switch (action.type) { 
     case ADD_DISCOUNT: 
      return { 
       ...state, 
       discounts: discounts(state.discounts, action) 
      }; 

     // etc etc 
    } 
} 

要了解更多,請查看丹本人的egghead.io redux series,特別是reducer composition視頻!

+1

該死的,打我幾秒 - 雖然很好的答案! – mxstbr

+7

事實上,你可以在應用程序中多次使用'combineReducers()'。我建議您在Redux回購中查看[購物車](https://github.com/reactjs/redux/tree/master/examples/shopping-cart/reducers)示例,其中演示了還原器組成的不同模式。 –

+3

這很酷,我沒有意識到這一點。然而,目標也不是儘可能平坦的狀態樹嗎?嵌套減速器和扁平狀態樹之間的平衡在哪裏? – Skitterm

3

你應該巢combinedReducers每個級別深

0

是,分離的減速器是一個正確的事情。實際上,如果您擔心其中一些操作需要更換其他減速器,您可以對其他減速器作出反應,或者只發送其他操作。

I've created a library解決此問題 - 以便於組合,並避免冗長的語法,以及合併結果。 所以,你的例子看起來像:

import { createTile, createSyncTile } from 'redux-tiles'; 

const cartItems = createSyncTile({ 
    type: ['account', 'cart'], 
    fn: ({ params }) => ({ items: params.items }) 
}); 

const coupons = createSyncTile({ 
    type: ['account', 'coupons'], 
    fn: ({ params }) => params, 
}); 

const reedemedCoupons = createSyncTile({ 
    type: ['account', 'reedemedCoupons'], 
    fn: ({ params }) => params.coupons 
}); 

const account = createTile({ 
    type: ['account', 'info'], 
    fn: ({ api }) => api.get('/client/info') 
}); 

使用這種策略的每個組件是原子,你可以輕鬆地創建新的調度等,在不影響其他人,這使得它更容易重構和刪除一些功能未來,當你的「瓷磚」遵循單一責任原則。

相關問題