2015-08-21 18 views
46

Was ist der beste/richtige Weg, um ein verschachteltes Datenfeld in einem Geschäft mit redux zu aktualisieren?Aktualisieren von verschachtelten Daten im Redux-Speicher

Mein Speicher wie folgt aussieht:

{ 
    items:{ 
     1: { 
      id: 1, 
      key: "value", 
      links: [ 
       { 
        id: 10001 
        data: "some more stuff" 
       }, 
       ... 
      ] 
     }, 
     ... 
    } 
} 

ich ein Paar asynchroner Aktionen habe, die das komplette items Objekt aktualisiert, aber ich habe ein anderes Paar von Aktionen, die in ein bestimmtes Verzeichnis links Array aktualisieren möchten.

derzeit Mein Minderer wie folgt aussieht, aber ich bin mir nicht sicher, ob dies der richtige Ansatz ist:

switch (action.type) { 
    case RESOURCE_TYPE_LINK_ADD_SUCCESS: 
     // TODO: check whether the following is acceptable or should we create a new one? 
     state.items[action.resourceTypeId].isSourceOf.push(action.resourceTypeLink); 
     return Object.assign({}, state, { 
     items: state.items, 
     }); 
    } 

Antwort

49

Reagieren der update() immutability helper eine bequeme Art und Weise ist es ohne mutiert eine aktualisierte Version eines einfachen alten JavaScript-Objekts zu erstellen .

Sie geben das Quellobjekt, das aktualisiert werden soll, und ein Objekt, das Pfade zu den Teilen beschreibt, die aktualisiert werden müssen und Änderungen, die vorgenommen werden müssen.

zB wenn eine Aktion hatte id und link Eigenschaften und Sie wollten die link auf eine Reihe von Links in einem Artikel mit dem id verkeilt drücken:

var update = require('react/lib/update') 

// ... 

return update(state, { 
    items: { 
    [action.id]: { 
     links: {$push: action.link} 
    } 
    } 
}) 

(Beispiel verwendet eine ES6 berechnet Eigenschaftsnamen für)

+5

Beachten Sie, dass update() zugunsten von https://github.com/kolodny/immutability-helper veraltet ist –

+0

Ich bin neugierig, warum Sie sich nicht für die Verwendung von 'Object.assign()' entschieden haben? – HussienK

+0

@HussienK Führt 'Object.assign' nicht zu einer flachen Kopie? –

57

Jonny's answer ist korrekt (mutieren Sie nie den Status, der Ihnen gegeben wurde!), Aber ich wollte einen weiteren Punkt hinzufügen. Wenn alle Ihre Objekte über IDs verfügen, ist es im Allgemeinen eine schlechte Idee, die Statusform verschachtelt zu lassen.

Dies:

{ 
    items: { 
    1: { 
     id: 1, 
     links: [{ 
     id: 10001 
     }] 
    } 
    } 
} 

ist eine Form, die schwer zu aktualisieren ist.

Es muss nicht so sein! Sie können es stattdessen speichern wie folgt aus:

{ 
    items: { 
    1: { 
     id: 1, 
     links: [10001] 
    } 
    }, 
    links: { 
    10001: { 
     id: 10001 
    } 
    } 
} 

So viel einfacher für die Aktualisierung ist, weil es nur eine kanonische Kopie jeder Einheit ist. Wenn Sie den Benutzer "einen Link bearbeiten" lassen müssen, gibt es nur einen Ort, wo er aktualisiert werden muss - und er ist völlig unabhängig von items oder irgendetwas anderem, bezogen auf links.

Um Ihre API-Antworten in eine solche Form zu bringen, können Sie normalizr verwenden. Sobald Ihre Einheiten innerhalb der Serveraktionen normalisiert sind, können Sie ein einfaches Minderer schreiben, die sie in den aktuellen Zustand übergeht:

import merge from 'lodash/object/merge'; 

function entities(state = { items: {}, links: {} }, action) { 
    if (action.response && action.response.entities) { 
    return merge({}, state, action.response.entities); 
    } 

    return state; 
} 

Bitte Redux real-world Beispiel für eine Demo solchen Ansatz sehen.

+0

Ich benutze normalizr, aber ich brauche auch die Elemente in der gleichen Reihenfolge, die sie in der API-Antwort kamen. Ich dachte über die Implementierung einer "verknüpften Liste" nach, die Entitäts-IDs verwendet, aber ich frage mich, ob es stattdessen einen besseren Ansatz gibt. –

+0

@hisa_py Sie sollten ein Array von IDs getrennt aufbewahren. Sowohl 'real-world'- als auch' shopping-cart'-Beispiele in Redux repo tun das. –

+1

Thx @Dan ... Schön und einfach ... Jetzt erinnere ich mich, ich sah es vorher in den Beispielen –

Verwandte Themen