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:
byId
) in einem früheren Zustand zeigt den gleichen Wert wie der letzte, auch wenn es vorher etwas anderes warIst 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.
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
Hilfreichster Kommentar
Auch Reduziererzusammensetzung hilft dabei.