2016-03-23 22 views
0

下記のRedux還元剤コード(主にUPDATE_TASKアクションとupdateTask還元剤機能に注意してください)では、私は自分の状態オブジェクトに単一のprojectを保存します。このprojectには複数のmilestonesがあり、順番には複数のtasksがあります。還元還元剤の改善

特定のタスクを更新すると、私はUPDATE_TASKアクションをトリガーしています。その後、PUT要求を実行し、taskの更新版をペイロードとして受信します。

次に、projectオブジェクトのmilestonesをすべて自分の状態から繰り返します。それがタスクのmilestone_idと一致する場合は、そのマイルストーンのtasksをすべて反復して、前のすべてのタスクを含むコレクションを作成し、応答から得たものを置き換えます。

これは、Reduxを使用して変更された状態を構築するアプローチに最も適していますか?また、私がやっているような非自明な状態更新のための関数を抽出することをお勧めしますか?私のコード(私が気づいていない文法やES6の練習のいずれか)で改善できる点は?

import { FETCH_PROJECT } from '../actions/index'; 
import { FETCH_PROJECTS } from '../actions/index'; 
import { FETCH_MILESTONES } from '../actions/index'; 
import { FETCH_TASKS } from '../actions/index'; 
import { UPDATE_TASK } from '../actions/index'; 

const INITIAL_STATE = { all: [], project: null, milestones: [] }; 

// injects a collection of tasks on the milestone that 
// matches the id we're using to fetch 
function updateTasks(state, action) { 
    const milestones = state.project.milestones.map((milestone) => { 
    if (milestone.id == action.meta.id) { 
     return { ...milestone, tasks: action.payload.data.tasks } 
    } 
    return milestone; 
    }); 
    const project = { ...state.project, milestones }; 

    return { ...state, project }; 
} 

// updates a single task on the proper milestone 
function updateTask(state, action) { 
    const { task } = action.payload.data; 
    const milestones = state.project.milestones.map((milestone) => { 
    if (milestone.id == task.milestone_id) { 
     const tasks = milestone.tasks.map((milestoneTask) => { 
     if (milestoneTask.id == task.id) { 
      return task; 
     } 
     return milestoneTask; 
     }); 

     return { ...milestone, tasks: tasks }; 
    } 
    return milestone; 
    }); 
    const project = { ...state.project, milestones }; 

    return { ...state, project }; 
} 

export default function(state = INITIAL_STATE, action) { 
    switch (action.type) { 
    case FETCH_PROJECT: 
     return { ...state, project: action.payload.data.project }; 

    case FETCH_PROJECTS: 
     return { ...state, all: action.payload.data.projects }; 

    case FETCH_MILESTONES: 
     return { ...state, milestones: action.payload.data.milestones }; 

    case FETCH_TASKS: 
     return updateTasks(state, action); 

    case UPDATE_TASK: 
     return updateTask(state, action); 
    } 

    return state; 
} 

答えて

3

実行するアクションのタイプによって、レデューサーが構築されます。より良い方法は、状態に含まれるデータの周りに減速機を構築することです。

はしたがって、あなたの初期状態では良い見てみましょう:

const INITIAL_STATE = { all: [], project: null, milestones: [] }; 

あなたはそれらのそれぞれに別々の減速を作成することができます。このような何かが働く可能性があります。

function projects(state={}, action) { 
    case FETCH_PROJECTS: 
     return action.payload.data.projects 
    ...etc 
} 

function activeProject(state={}, action) { 
    case FETCH_PROJECT: 
     return action.payload.data.project 
    case FETCH_MILESTONES: 
     // add milestone to appropriate project 
} 

function milestones(state={}, action) { 
    case FETCH_MILESTONES: 
     // add milestone 
    case FETCH_TASKS: 
     // add task to appropriate milestone 

} 

function tasks(state={}, action) { 
    case FETCH_TASKS: 
     // update appropriate task 
} 

その後、あなたはcombineReducersを使用して、これらすべての減速を組み合わせることができ、またはあなたはそれらを自分で組み合わせています。

日付を構成するには、https://github.com/gaearon/normalizrをご覧ください。アイデアは、あなたのレデューサーのデータを可能な限りフラットに保つことです。この方法では、ネストされたレデューサーは必要なく、複雑さを避けることができます。

あなたの例では、すべてのマイルストーンは、このようなオブジェクトを作成するタスクのリストかもしれない:

{ 
    m1: { tasks: [t1,t2], ...} 
    m2: { tasks: [t3], ...} 
    m3: { tasks: [t4,t5], ...} 
} 

をそして、あなたのタスクは次のようにその内容にオブジェクトマッピングIDSのようになります。

{ 
    t1: {} //task 
    t2: {} //task 
    t3: {} //task 
    t4: {} //task 
    t5: {} //task 
} 

プロジェクトとマイルストーンについても同じことが言えます。

関連する問題