2015-10-24 11 views
7

スプリットレデューサーを維持しながら、私の状態ツリーのいくつかのトップレベルフィールドを更新する理想的な方法を試しています。スプリットレデューサーで関連する状態フィールドを更新する最も良い方法は?

は、ここで私が作ってみたシンプルなソリューションです。

var state = { 
    fileOrder: [0], 
    files: { 
    0:{ 
     id: 0, 
     name: 'asdf' 
    } 
    } 
}; 

function handleAddFile(state, action) { 
    return {...state, ...{[action.id]:{id: action.id, name: action.name}}}; 
}; 

function addFileOrder(state, action) { 
    return [...state, action.id]; 
} 

// Adding a file should create a new file, and add its id to the fileOrder array. 
function addFile(state, action) { 
    let id = Math.max.apply(this, Object.keys(state.files)) + 1; 
    return { 
    ...state, 
    fileOrder: addFileOrder(state.fileOrder, {id}), 
    files: handleAddFile(state.files, {id, name: action.name}) 
    }; 
} 

現在、私は、単一のアクション{type: ADD_FILE, fileName: 'x'}を派遣することができるよ、そしてaddFileaddFileOrderaddFileに送信するために内部でアクションを作成します。それは以下のいずれかを行うには良いアプローチと見なされた場合

私は興味があります。

代わりに、ファイルを追加するために、2つのアクション、1を派遣それは、IDのgetとidでADD_TO_FILE_ORDERアクションを派遣。 に新しいIDを計算させるのではなく、{type: ADD_FILE, name: 'x', id: 1}のように、火災と行動を にしてください。これにより、私はcombineReducersを使用し、アクションタイプにフィルタを適用できます。 この例はおそらく些細なものですが、私の実際の状態ツリーはもう少し複雑で、各ファイルもまた他のエンティティに追加する必要があります。

いくつかの追加のコンテキストでは、より完全な状態のツリーは次のようになります。

{ 
    "fileOrder": [0] 
    "entities": { 
     "files": { 
      0: { 
       id: 0, 
       name: 'hand.png' 
      } 
     }, 
     "animations": { 
      0: { 
       id: 0, 
       name: "Base", 
       frames: [0] 
      } 
     }, 
     "frames": { 
      0: { 
       id: 0, 
       duration: 500, 
       fileFrames: [0] 
      } 
     }, 
     "fileFrames": { 
      0: { 
       id: 0, 
       file: 0, 
       top: 0, 
       left: 0, 
       visible: true 
      }   
     } 
    } 
} 

する必要がありますファイルを追加:

  1. は、ファイルのハッシュに追加します。
  2. fileOrder配列に追加します。
  3. 各フレームのファイルを参照するfileFrameを追加します。
  4. それぞれの新しいfileFrameを、作成されたフレームに追加します。

最後の2つの点は、私がcombineReducersをまったく使用できるかどうか疑問に思います。

答えて

7

私はこの問題のかなり簡単な解決策を見つけました。ドキュメントからこれらのブロックの

の両方が機能的に同じものです。

const reducer = combineReducers({ 
    a: doSomethingWithA, 
    b: processB, 
    c: c 
}); 

// This is functionally equivalent. 
function reducer(state, action) { 
    return { 
    a: doSomethingWithA(state.a, action), 
    b: processB(state.b, action), 
    c: c(state.c, action) 
    }; 
} 

私は2番目のブロックを微調整し、常にグローバル状態ツリーを渡しました。途中で状態を編集するものがない限り、すべての減速機が正常に動作します。著者のソリューションに

// Simple change to pass the entire state to each reducer. 
// You have to be extra careful to keep state immutable here. 
function reducer(state, action) { 
    return { 
    a: doSomethingWithA(state.a, action, state), 
    b: processB(state.b, action, state), 
    c: c(state.c, action, state) 
    }; 
} 
2

ビル:

私は状態の私の減速の部分の外側(ほんの少し)のアクセスを必要とする、この同じ問題を、持ってきました。私は、フラグやカウンターのような単一の値以外を変更しないことに勤勉であれば、この解決策が実際に機能すると思います。

これは、他の開発者が彼らのコードのように予約されていなかった場合、不純物が速いクレイジー得ることができるのです。 bとcが状態の一部を変更し始めた場合、aとcの部分を変更するなど、何が起こるかを想像してください。

function reducer(state, action) { 
    return { 
    a: doSomethingWithA(state.a, action, state.globals), 
    b: processB(state.b, action, state.globals), 
    c: c(state.c, action, state.globals) 
    }; 
} 
:あなたはこのように、不純物の面積を縮小検討するかもしれない

関連する問題