2015-11-16 3 views
10

Ich verwende redux mit normalizr, um die Antwort vom Server zu normalisieren, im Grunde die Beispiel folgen. Auf diese Weise entities Reducer ist sehr einfach, nur die Antwort zusammenführen. Das Problem, das ich gerade habe, ist eine Art delete Operation. Ich habe dieses issue#21 of normalizr repo gefunden, aber konnte noch nicht herausfinden, wie man das löst. Zum BeispielRedux + Normalizr getrennt (gelöscht) Betrieb

Aktueller Stand ist

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

Die normalisierte Antwort ist

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

Wie Sie sehen können, nur das Backend api alle Produkt-IDs zurückgibt, die zu dieser Kategorie gehörte, in dieser Fall "2" ist gelöst. Wenn der Reduzierer "Entitäten" diese Antwort zusammenführt, bleibt "2" immer noch hängen. Im Moment lade ich einfach die Seite neu, aber ich frage mich, ob es einen besseren Weg gibt, mit diesem Fall umzugehen?

In entities Reducer, ich füge es einfach wie in der realen Welt Beispiel.

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

+1

Dies ist eine wirklich gute Frage. IMO weist es auf einen wesentlichen Fehler in der gesamten Redux + Normalizr-Architektur hin. Sicher, Sie haben eine einzige Wurzel zu sagen, aber es ist nicht genau eine wahrheitsgetreue Darstellung. Die Verwendung von Löschflags ist viel zu eigensinnig. –

Antwort

12

Nur keine Sorge um ihn dort zu sein. Stellen Sie sich Ihren Status als Datenbank vor. Sie löschen Datensätze nicht wirklich aus der Datenbank, um komplizierte Kaskaden zu vermeiden - normalerweise ändern Sie einfach ihren Status in der Datenbank. Genauso sollten Sie im Normalizer die Entitäten wirklich löschen, indem Sie sie im Cache lassen, bis der Benutzer die Seite verlässt!

+0

Was meinen Sie mit "Sie löschen Datensätze nicht wirklich aus der Datenbank"? –

+0

Anstatt ein Element aus einem Array zu entfernen, fügen Sie ein Flag namens "gelöscht" oder etwas hinzu. Dann aktualisiere deinen Selektor auf 'items.filter (item =>! Item.deleted)' –

0

Im Folgenden finden Sie eine Erklärung meiner Lösung gefolgt von Code.

Um einen Löschvorgang durchzuführen, habe ich meinen Reducer auf einen Handle und eine Löschaktion aktualisiert: REMOVE_ENTITY_ITEM. In der Aktion gebe ich die id und name der Entität, die entfernt werden soll.

Im Reducer lösche ich zuerst die Einheit selbst, die store.entities[entityName][entityId] ist. Als nächstes muss ich seine id von allen anderen Entitäten entfernen, die sich darauf beziehen könnten. Da ich verwende, sind alle meine Entitäten flach und wenn sie sich auf eine andere Entität beziehen, dann haben sie nur ihre ID in einem Array. Dies macht es relativ einfach, die Referenz zu entfernen. Ich mache einfach eine Schleife über alle Entitäten und filtere den Verweis auf die Entität, die entfernt wird.

Ich benutze diesen Ansatz in Verbindung mit den beiden anderen Ansätze von # 1.) Aktualisieren der App/Zustand und # 2.) Spiegeln der Entitäten Statusbit, anstatt zu löschen und dann die ausgeschalteten Elemente in der Benutzeroberfläche zu filtern. Diese Ansätze wurden gut here diskutiert

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

Jetzt löschen i Feuer eine Aktion wie folgt aus:

store.dispatch({ 
    type: "REMOVE_ENTITY_ITEM", 
    meta: { 
    id: 1, 
    name: "job_titles" 
    } 
});