web-dev-qa-db-fra.com

Est-ce la bonne façon de supprimer un élément en utilisant redux?

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?

93
CWright

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)
],
169
David L. Walsh

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() 
})
121
Steph M

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() 
})
16
JoeTidee

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;
3
Roman