Redux: Frage: Mutation eines inneren Objekts in einen Zustand in einem Reduzierer

Erstellt am 15. Apr. 2016  ·  3Kommentare  ·  Quelle: reduxjs/redux

Ist dies ein gültiger Redux-Reduzierer?

function reducer(state={ byId: {}, ids: [] }, action) {
  switch (action.type) {
    case 'ADD':
      state = { ...state }
      state.byId[action.id] = action.value
      state.ids.push(action.id)
      return state

    default:
      return state
  }
}

Der gesamte Zustand wird zuerst flach geklont, sodass ein neues Objekt zurückgegeben wird, die inneren Objekte jedoch unverändert bleiben und mutiert werden.

Oder muss ich so etwas tun:

function reducer(state={ byId: {}, ids: [] }, action) {
  switch (action.type) {
    case 'ADD':
      return {
        ...state,
        byId: {
          ...state.byId,
          [action.id]: action.value
        },
        ids: [ ...state.ids, action.id ]
      }

    default:
      return state
  }
}

Die Nebenwirkungen, die ich beim ersten Ansatz sehe, sind in DevTools LogMonitor:

  • Das Erweitern eines Unterknotens (z. B. byId ) in einem früheren Zustand zeigt den gleichen Wert wie der letzte, auch wenn es vorher etwas anderes war
  • Zeitreisen funktionieren nicht

Ist es nur ein Bug im LogMonitor oder ist der zweite Ansatz der richtige? Wenn ich vor den Mutationen state = _.cloneDeep(state) hinzufüge, funktioniert es tatsächlich gut und beweist, dass der LogMonitor dieselben Objekte wiederverwendet, daher dieselben Werte.

Der Rest der App funktioniert einwandfrei und @connect Ed-Ansichten werden jedoch korrekt aktualisiert.

Hilfreichster Kommentar

Das letztere Beispiel ist das, was Sie tun müssen. Offensichtlich kann das etwas ausführlich werden, wenn Sie Dinge verschachteln. Es gibt mehrere Hilfsbibliotheken, die versuchen, dies für Sie zu abstrahieren, und ich habe einige davon auf der Seite Unveränderliche Daten meiner Redux-Bibliotheksliste aufgeführt.

Auch Reduziererzusammensetzung hilft dabei.

function byId(state = {}, action) {
  switch (action.type) {
    case 'ADD':
      return {
        ...state,
        [action.id]: action.value
      }
    default:
      return state
  }
}

function ids(state = [], action) {
  switch (action.type) {
    case 'ADD':
      return [ ...state, action.id ]
    default:
      return state
  }
}

const reducer = combineReducers({
  byId,
  ids
})

Alle 3 Kommentare

Nein, dieses erste Beispiel mutiert den Zustand absolut. Die anfängliche flache Kopie erstellt ein neues Objekt, aber das neue Objekt zeigt auf dieselben byId - und ids -Referenzen wie das Original. Wenn Sie also byId[action.id] = action.value und ids.push(action.id) machen, mutieren Sie die ursprünglichen Elemente.

Das letztere Beispiel ist das, was Sie tun müssen. Offensichtlich kann das etwas ausführlich werden, wenn Sie Dinge verschachteln. Es gibt mehrere Hilfsbibliotheken, die versuchen, dies für Sie zu abstrahieren, und ich habe einige davon auf der Seite Unveränderliche Daten meiner Redux-Bibliotheksliste aufgeführt.

Die Redux-FAQ enthält auch eine Frage, die sich mit der unveränderlichen Aktualisierung des Status befasst: http://redux.js.org/docs/FAQ.html#react -not-rendering .

Das letztere Beispiel ist das, was Sie tun müssen. Offensichtlich kann das etwas ausführlich werden, wenn Sie Dinge verschachteln. Es gibt mehrere Hilfsbibliotheken, die versuchen, dies für Sie zu abstrahieren, und ich habe einige davon auf der Seite Unveränderliche Daten meiner Redux-Bibliotheksliste aufgeführt.

Auch Reduziererzusammensetzung hilft dabei.

function byId(state = {}, action) {
  switch (action.type) {
    case 'ADD':
      return {
        ...state,
        [action.id]: action.value
      }
    default:
      return state
  }
}

function ids(state = [], action) {
  switch (action.type) {
    case 'ADD':
      return [ ...state, action.id ]
    default:
      return state
  }
}

const reducer = combineReducers({
  byId,
  ids
})

@gaearon @markerikson Danke. Am Ende habe ich einen High-Order-Reducer geschrieben, der dynamische indizierte Listen (nach ID) verwaltet.

Code: https://gist.github.com/elado/95484b754f31fcd6846c7e75de4aafe4

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

markerikson picture markerikson  ·  51Kommentare

ghost picture ghost  ·  50Kommentare

wmertens picture wmertens  ·  55Kommentare

nickknw picture nickknw  ·  71Kommentare

EricSimons picture EricSimons  ·  45Kommentare