2016-03-11 18 views
21

レビュックスで深くネストされた状態を変更する方法について、私は頭を抱えています。レデューサーを組み合わせて、これらの部分の状態の第1レベルのプロパティを変更することは意味があります。私があまり明確でないところでは、深く入れ子になった財産の状態を変える方法があります。 私はショッピングカートアプリを持っているとしましょう。以下は私の状態です:Reduxレデューサー - 深入れネスト状態の変更

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

ユーザーがコードに入ると、のは、彼らが「buyOneGetOne」クーポンを可能としましょう、その値がtrueになる必要があります。 私はカートのための減速機を持っていて、アカウントのために別のものを持っています。最初のレベルのプロパティ(のような私は、カートの項目をクリアした場合)のために、私はちょうど私の減速で次の操作を行います:

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

buyOneGetOneを変更するために、しかし、私が最初に実行する必要がありますように思えます(クーポンを変更したので)割引でObject.assignを行い、最後にレデューサーがObject.assignを行うことができるようにアクションを実行します(ディスカウントは今ではかわった)。これは本当に複雑で間違っているように思えますが、それはよりよい方法が必要であると信じさせてくれます。

私はこれについてすべて間違っていますか?レデューサーは州のルートレベルのプロパティ(カートやアカウントなど)を変更するためにのみ使用され、アカウントには減速機があるため、アカウント内の状態に触れるレデューサー(割引レデューサーなど)を使用しないでください。しかし、私はステートツリーの1つのプロパティを遠くに変更したいときは、すべてのオブジェクトをそのオブジェクトチェーンからルートの子にまでマージするのが複雑になります。

この場合のようにレデューサーの内部にレデューサーを持っていますか?

答えて

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レポの[shopping-cart](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') 
}); 

を各コンポーネントがアトミックである、とあなたは簡単に他の人に影響を与えずに、新しく派遣他人を作成することができ、それはそれが簡単にいくつかの機能をリファクタリングして除去することができますあなたの「タイル」が単一責任の原則に従っているとき、未来。

関連する問題