2016-05-11 17 views
0

Also habe ich daran gearbeitet, eine APP in React Native zu machen, für die ich eine RESTFul API in Java programmiert habe, die einige Daten im JSON Format zurückgibt. Ich werde eine Datenstruktur haben, die ungefähr so ​​aussieht - es ist auch der Ausgangszustand für dieses Reducer ist, ich habe einfach einige der Werte gestrichen, da sie nicht relevant sind:Bearbeiten von Daten in verschachtelten Arrays in Redux mit immutable.js

categories: [{ 
    id: 1, 
    name: '', 
    image: '', 
    subcategories: [ 
     { 
      name: '', 
      id: 1, 
      products: [{ 
       name: '', 
       description: 'This is a good product', 
       id: 55, 
       quantity: 4 
      }, { 
       name: '', 
       description: 'This is a good product', 
       id: 3, 
       quantity: 0 
      }] 
     }, 
     { 
      name: '', 
      id: 2, 
      products: [{ 
       name: '', 
       description: 'This is a good product', 
       id: 4, 
       quantity: 0 

      }] 
     }] 
}, { 
    id: 2, 
    name: '', 
    image: '', 
    subcategories: [ 
     { 
      name: '', 
      id: 3, 
      products: [{ 
       name: '', 
       description: 'This is a good product', 
       id: 15, 
       quantity: 0 

      }] 
     } 

    ] 
}] 

werde ich dies in meinem Redux Speicher gespart werden aber wo ich kämpfe ist, wenn ich die menge eines bestimmten produkts mit nur der produkt-id aktualisieren muss. Bis jetzt habe ich eine Lösung mit immutable.js gefunden, aber es ist ziemlich hässlich und ich bin mir nicht sicher, ob das der richtige Weg ist.

Ich habe nach Lösungen gesucht, aber noch keine mit einer Lösung gefunden, ohne die Datenstruktur zu normalisieren. Im Moment möchte ich sehen, ob ich es vermeiden kann, die Daten zu normalisieren, da ich das gleiche Format für das Zurücksenden von Daten auf dem Server beibehalten möchte. (Und zu Lernzwecken)

Meine Lösung in meinem Reducer mit immutable.js sieht wie folgt aus:

case types.ADD_PRODUCT: 

     const oldState = fromJS(state).toMap(); 

     var findCategoryIndex = oldState.get('categories').findIndex(function (category) { 
      return category.get("subcategories").find(function (subcategories) { 
       return subcategories.get("products").find(function (product) { 
        return product.get("id") === action.productId; 
       }) 
      }) 
     }) 

     var findSubcategoryIndex = oldState.getIn(['categories', findCategoryIndex.toString()]).get('subcategories').findIndex(function (subcategory) { 
      return subcategory.get("products").find(function (product) { 
       return product.get("id") === action.productId; 
      }); 
     }) 

     var findProductIndex = oldState.getIn(['categories', findCategoryIndex.toString(), 'subcategories', findSubcategoryIndex.toString()]).get('products').findIndex(function (product) { 
       return product.get("id") === action.productId; 
     }) 


     var newState = oldState.setIn(['categories', findCategoryIndex.toString(), 
      'subcategories', findSubcategoryIndex.toString(), 'products', findProductIndex.toString(), 'quantity'], 
     oldState.getIn(['categories', findCategoryIndex.toString(), 'subcategories', findSubcategoryIndex.toString(), 'products', findProductIndex.toString(), 'quantity'])+1); 


     const newStateJS = newState.toJS(); 


     return {...state, categories: [...newStateJS.categories]} 

Ich weiß, all dies kann für den Fall zu kompliziert erscheinen, aber ich versuche, einfach verschiedene Ansätze zu lernen Dazu bin ich sehr neu in allem was mit JavaScript zu tun hat.

Ich bin nicht für die Optimierung des Datenformates suche selbst, aber ich bin auf der Suche nach Möglichkeiten, Daten in verschachtelter Arrays in Redux

zu manipulieren Ich hoffe, einiges gutes Feedback auf diese zu bekommen und hoffentlich herausfinden, ob ich bin auf dem richtigen Weg :)

EDIT: Es funktioniert mit Spread-Operatoren auch ohne Immutable.js, aber ich verstehe nicht wirklich, was der Unterschied ist. Gibt es einen Leistungsunterschied und warum wählen Sie einen über den anderen?

case types.ADD_PRODUCT: 
     return { 
      ...state, 
      categories:[...state.categories.map(category => ({...category, 
       subcategories:[...category.subcategories.map(subcategory => ({...subcategory, 
        products:[...subcategory.products.map(product => product.id === action.productId ? {...product, quantity: product.quantity+1} : product)]}))]}))] 
     } 

Antwort

2

Wenn es die Daten ein wenig zu tief sind, können Sie immer noch Helfer wie Immutable.js Map verwenden. Ich bin nicht sicher, dass dies der richtige Weg ist, Immutable.js zu verwenden, da ich auch damit experimentiere. Damit können Sie neuen Zustand in eine weniger ausführlich Art und Weise wie diese zurückgeben:

import { fromJS } from 'immutable'; 

export default function reducer(state = initialState, action) {  
    const iState = fromJS(state);// Immutable State 
    switch (action.type) { 
    case type.ACTION: 
     return iState.setIn(['depth1','depth2', 'depth3'], 'foobar').toJS() 
// return a copy of the state in JavaScript 
// {depth1: {depth2: {depth3: 'foobar'} } } 
    default: 
    return state; 
} 

und von dem, was ich gehört habe, Immutable mit mehr performant aber es fügt eine andere Abhängigkeit zu Ihrem Projekt. Vorsicht, wenn Sie combineReducers(reducers), it expects to be pass a plain object verwenden, sollten Sie also ein einfaches Objekt und kein unveränderliches Objekt übergeben.

Sie haben gesagt, dass Sie nicht speziell für die Optimierung des Datenformats selbst suchen. Korrigieren Sie mich, wenn ich falsch liege, denke ich normalizr wird Ihnen helfen, in der Flachheit zu gewinnen und einfacher zu sein, Ihr Geschäft zu aktualisieren

Verwandte Themen