2015-11-16 14 views
10

私はreduxをnormalizrで使用してサーバーからの応答を正規化します。基本的にreal-worldの例に従ってください。この方法でentities減速機は非常に簡単です、ちょうど応答をマージします。今私が持っている問題は、delete操作のようなものです。私はこれを見つけましたissue#21 of normalizr repoしかし、これを解決する方法をまだ理解できませんでした。例えば、Redux + Normalizr detached(deleted)操作

現在の状態が

{ 
    entities: 
    product_categories: { 
     ... 
     13: { 
     ... 
     products: ["1", "2"], <--------------- [i] Current state 
     ... 
     } 
    }, 
    products: { 
     1: { 
     id: "1" 
     } 
    } 
} 

正規化された応答は、あなたが見ることができるように、バックエンドAPIはちょうどで、このカテゴリに属しすべての製品IDを返し

{ 
    ... 
    product_categories: { 
     ... 
     13: { 
     ... 
     products: ["1"], <---------------- [2] Normalized result 
     } 
    ... 
} 

ですこの場合「2」が切り離される。 'エンティティ'レデューサーがこのレスポンスをマージすると、「2」は依然としてハングしています。今はページをリロードするだけですが、このケースを処理するにはより良い方法があるのだろうかと思います。

entitiesでは、実際の例のようにマージします。

return merge({}, state, action.payload.entities);

+1

これは本当に良い質問です:これらのアプローチは、よく私はこのようなアクションを発射削除するhere

const entities = (state={}, action) => { if(action.payload && action.payload.entities) { return merge({} , state, action.payload.entities); }else{ return deleteHandlingReducer(state, action) } } const deleteHandlingReducer = (state=initialSate, action) => { switch(action.type){ case "REMOVE_ENTITY_ITEM": if (!action.meta || !action.meta.name || !action.meta.id) { return state; }else{ let newState = Object.assign({}, state); if(newState[action.meta.name]){ delete newState[action.meta.name][action.meta.id]; Object.keys(state).map(key => { let entityHash = state[key]; Object.keys(entityHash).map(entityId => { let entity = entityHash[entityId]; if(entity[action.meta.name] && Array.isArray(entity[action.meta.name])){ entity[action.meta.name] = entity[action.meta.name]. filter(item => item != action.meta.id) } }); }) } return newState; } default: return state; } } 

を議論してきました。 IMOは、Redux + Normalizrアーキテクチャ全体に大きな欠陥があることを指摘しています。確かにあなたは単一の根源を持っていますが、まさに真実な表現ではありません。削除フラグの使用を要求することは、あまりにもひどいです。 –

答えて

12

ちょうどそれがそこにあることについて心配しないでください。あなたの状態をデータベースと考えてください。複雑なカスケードを回避するために、データベースからレコードを削除することは本当にありません。通常、データベース内のステータスを変更するだけです。同様に、ノーマライザでは、本当にエンティティを削除するのではなく、ユーザーがページを離れるまでキャッシュに置くようにしてください!

+0

「あなたは本当にデータベースからレコードを削除しないのですか? –

+0

配列からアイテムを削除する代わりに、 "deleted"という名前のフラグを追加します。セレクタを 'items.filter(item =>!item.deleted)'に更新します。 –

0

以下は、私の解決策とそれに続くコードの説明です。

削除を実行するには、私のレデューサーを削除アクションの処理に更新しました:REMOVE_ENTITY_ITEM。私は、取り除かれるエンティティのidnameを渡します。

還元剤では、まず、store.entities[entityName][entityId]にあるエンティティ自体を削除します。次に、それを参照しているかもしれない他のすべてのエンティティからそのidを削除する必要があります。私はnormalizrを使用しているので、すべてのエンティティはフラットであり、別のエンティティを参照すると、そのIDは配列内にのみ存在します。これにより、参照を削除するのが比較的簡単になります。私はすべてのエンティティをループし、削除されるエンティティへの参照をフィルタリングします。

私はこのアプローチを#1の他の2つのアプローチと併用しています。UIの中のオフになっている項目を削除してからフィルタリングするのではなく、エンティティのステータスビットを反転してアプリと状態をリフレッシュします。

store.dispatch({ 
    type: "REMOVE_ENTITY_ITEM", 
    meta: { 
    id: 1, 
    name: "job_titles" 
    } 
}); 
関連する問題