2016-03-23 34 views
0

Aşağıdaki Redux redüktör kodunda (UPDATE_TASK eylemine ve esas olarak updateTask redüktör fonksiyonuna dikkat edin), tek bir project durum satırımda tutuyorum. Bu project'un birden fazla milestones vardır; bu, sırası ile birden çok tasks'a sahiptir.Redux redüktörlerinin iyileştirilmesi

Verilen bir görevi güncelleştirdiğimde, UPDATE_TASK eylemini tetikliyorum. Daha sonra bir PUT isteği gerçekleştirir ve task'un güncellenmiş sürümünü, faydalı yük olarak alır.

Sonraki aşamada, project nesnesinin milestones nesnesinin tümünü durumumdan yineliyorum. Görevin milestone_id ile eşleşmesi durumunda, bu dönüm noktasının tasks tümünün üzerinden yinelemeye devam ederek, önceki tüm görevleri içeren bir toplama oluşturarak yanıtı aldığımdan değiştiririm.

Redux'u kullanarak değiştirilmiş durumu oluşturmaya yaklaşmanın en iyi yolu bu mu? Ayrıca, yaptığım gibi önemsiz olmayan durum güncellemeleri için işlevler çıkarılması tavsiye edilir mi? Kodumda ne geliştirilebilir (ya stilist ya da farkında olmadığım ES6 numaraları)?

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; 
} 

cevap

3

Redüktörlerinizi, yaptığınız işlemlerin türü etrafında geliştirirsiniz. Redüktörlerinizi, devletin içerdiği veri etrafında oluşturmak için daha iyi bir yol olurdu.

Dolayısıyla başlangıçtaki durumuna iyice bir göz atın:

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

bunlardan her biri için ayrı düşürücü oluşturabilir. Böyle bir şey işe yarayabilir.

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 
} 

Sonra ilerde combineReducers kullanarak tüm bu düşürücüler birleştirebilir veya bunları kendiniz birleştirin.

Tarihinizi yapılandırırken yardım almak için https://github.com/gaearon/normalizr'a bakın. Fikir, verilerinizi redüktörünüzde mümkün olduğunca düz bir şekilde temsil etmektir. Bu sayede yuvalanmış redüktörlere ihtiyacınız olmaz ve karmaşıklığı önlersiniz. Örnekte

, her kilometre taşı böyle bir nesneyi oluşturma görevlerin listesini olabilir:

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

Ve görevleri gibi onların içeriğine bir nesne eşleme kimlikleri olabilir:

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

Ve projeler ve kilometre taşları için aynı şey, onları aynı şekilde ilişkilendirir.