Je sais que je ne suis pas censé muter l'entrée et que je devrais cloner l'objet pour le muter. Je suivais la convention utilisée sur un projet de démarrage Redux qui utilisait:
ADD_ITEM: (state, action) => ({
...state,
items: [...state.items, action.payload.value],
lastUpdated: action.payload.date
})
pour ajouter un élément - je reçois l'utilisation de spread pour ajouter l'élément dans le tableau.
pour supprimer j'ai utilisé:
DELETE_ITEM: (state, action) => ({
...state,
items: [...state.items.splice(0, action.payload), ...state.items.splice(1)],
lastUpdated: Date.now()
})
mais cela modifie l'objet d'état d'entrée - est-ce interdit même si je retourne un nouvel objet?
Non, ne jamais muter votre état.
Même si vous retournez un nouvel objet, vous continuez à polluer l'ancien, ce que vous ne voulez jamais faire. Cela rend la comparaison problématique entre l'ancien et le nouvel État problématique. Par exemple dans shouldComponentUpdate
qui réagit-redux utilise sous le capot. Cela rend également le voyage dans le temps impossible (c'est-à-dire annuler et rétablir).
Au lieu de cela, utilisez des méthodes immuables. Utilisez toujours Array#slice
et jamais Array#splice
.
Je suppose d'après votre code que action.payload
est l'index de l'élément en cours de suppression. Une meilleure façon serait comme suit:
items: [
...state.items.slice(0, action.payload),
...state.items.slice(action.payload + 1)
],
Vous pouvez utiliser la méthode de filtrage de tableau pour supprimer un élément spécifique d'un tableau sans modifier l'état d'origine.
return state.filter(element => element !== action.payload);
Dans le contexte de votre code, cela ressemblerait à ceci:
DELETE_ITEM: (state, action) => ({
...state,
items: state.items.filter(item => item !== action.payload),
lastUpdated: Date.now()
})
La méthode ES6 Array.prototype.filter
renvoie un nouveau tableau avec les éléments correspondant aux critères. Par conséquent, dans le contexte de la question initiale, ce serait:
DELETE_ITEM: (state, action) => ({
...state,
items: state.items.filter(item => action.payload !== item),
lastUpdated: Date.now()
})
Une autre variante du réducteur immuable "DELETED" pour le tableau avec objets:
const index = state.map(item => item.name).indexOf(action.name);
const stateTemp = [
...state.slice(0, index),
...state.slice(index + 1)
];
return stateTemp;