Quelle est la meilleure façon/correcte de mettre à jour un tableau imbriqué de données dans un magasin en utilisant redux?
Mon magasin ressemble à ceci:
{
items:{
1: {
id: 1,
key: "value",
links: [
{
id: 10001
data: "some more stuff"
},
...
]
},
...
}
}
J'ai une paire d'actions asynchrones qui met à jour l'objet complet items
mais j'ai une autre paire d'actions que je souhaite mettre à jour un tableau spécifique links
.
Mon réducteur ressemble actuellement à ceci, mais je ne suis pas sûr que ce soit la bonne approche:
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,
});
}
React update()
assistant de l'immuabilité est un moyen pratique de créer une version mise à jour d'un ancien objet JavaScript simple sans le muter.
Vous lui donnez l'objet source à mettre à jour et un objet décrivant les chemins d'accès aux pièces à mettre à jour et les modifications à apporter.
par exemple, si une action avait les propriétés id
et link
et que vous vouliez transférer le link
dans un tableau de liens dans un élément associé au id
:
var update = require('react/lib/update')
// ...
return update(state, {
items: {
[action.id]: {
links: {$Push: action.link}
}
}
})
(Exemple utilise un nom de propriété calculé ES6 pour action.id
)
La réponse de Jonny est correcte (ne modifiez jamais l'état qui vous a été attribué!) Mais je voulais ajouter un autre point. Si tous vos objets ont des ID, il est généralement déconseillé de conserver la forme de l'état imbriquée.
Cette:
{
items: {
1: {
id: 1,
links: [{
id: 10001
}]
}
}
}
est une forme difficile à mettre à jour.
Ce ne doit pas être comme ça! Vous pouvez plutôt le stocker comme ceci:
{
items: {
1: {
id: 1,
links: [10001]
}
},
links: {
10001: {
id: 10001
}
}
}
C'est beaucoup plus facile pour la mise à jour car il n'y a qu'une seule copie canonique de toute entité. Si vous devez laisser l’utilisateur “éditer un lien”, il n’ya qu’un endroit où il doit être mis à jour - et il est complètement indépendant de items
ou de tout autre élément faisant référence à links
.
Pour obtenir vos réponses API dans une telle forme, vous pouvez utiliser normalizr . Une fois que vos entités au sein des actions du serveur sont normalisées, vous pouvez écrire un simple réducteur qui les fusionne dans l'état actuel:
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;
}
S'il vous plaît voir Redux real-world
exemple pour une démonstration de cette approche.