Est-ce un réducteur de redux valide?
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
}
}
L'état entier est d'abord cloné superficiellement, donc un nouvel objet sera renvoyé, mais les objets internes restent les mêmes et mutés.
Ou dois-je faire quelque chose comme:
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
}
}
Les effets secondaires que je vois avec la première approche sont dans DevTools LogMonitor :
byId
) dans un état précédent affichera la même valeur que le dernier même s'il s'agissait d'autre chose auparavantEst-ce juste un bogue dans le LogMonitor ou la seconde approche est-elle la bonne ? Si j'ajoute state = _.cloneDeep(state)
avant les mutations, cela fonctionne bien, prouvant que le LogMonitor réutilise les mêmes objets, donc les mêmes valeurs.
Le reste de l'application fonctionne bien et les vues @connect
ed se mettent à jour correctement.
Non, ce premier exemple est en train de muter absolument l'état. La copie superficielle initiale crée un nouvel objet, mais le nouvel objet pointe vers les mêmes références byId
et ids
que l'original. Ainsi, lorsque vous faites byId[action.id] = action.value
et ids.push(action.id)
, vous modifiez les éléments d'origine.
Ce dernier exemple est ce que vous devez faire. Évidemment, cela peut devenir un peu verbeux si vous imbriquez des choses. Il existe plusieurs bibliothèques utilitaires qui tentent de résumer cela pour vous, et j'en ai certaines répertoriées dans la page Données immuables de ma liste de bibliothèques Redux.
La FAQ Redux a également une question qui couvre correctement la mise à jour de l'état de manière immuable : http://redux.js.org/docs/FAQ.html#react -not-rerendering .
Ce dernier exemple est ce que vous devez faire. Évidemment, cela peut devenir un peu verbeux si vous imbriquez des choses. Il existe plusieurs bibliothèques utilitaires qui tentent de résumer cela pour vous, et j'en ai certaines répertoriées dans la page Données immuables de ma liste de bibliothèques Redux.
La composition du réducteur aide également à cela.
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 Merci. J'ai fini par écrire un réducteur d'ordre élevé qui gère des listes indexées dynamiques (par ID)
Code : https://gist.github.com/elado/95484b754f31fcd6846c7e75de4aafe4
Commentaire le plus utile
La composition du réducteur aide également à cela.