web-dev-qa-db-fra.com

Supprime les données des objets imbriqués sans mutation

Existe-t-il un moyen élégant de supprimer un objet d’un tableau faisant partie d’un tableau? Je travaille avec React et Redux depuis quelque temps déjà, mais je suis bloqué plusieurs heures à chaque fois que je dois supprimer ou insérer des données sans la mutation de l'état.

Le réducteur est un tableau contenant des objets ayant un ID et un autre tableau avec des objets, comme ceci:

[
 { id:123,
   items:[
           { id: abc,
             name: albert
           }, 
           ... 
         ]
 }, 
 ... 
]

Je reçois les deux identifiants et j'ai besoin de supprimer l'élément avec l'identifiant abc

14
Daniel Storch

Pour supprimer un élément d'un tableau par identifiant:

return state.filter(item => item.id !== action.id)

Pour supprimer une clé d'un objet à l'aide de son identifiant:

let copy = Object.assign({}, state) // assuming you use Object.assign() polyfill!
delete copy[action.id] // shallowly mutating a shallow copy is fine
return copy

(Bonus) Idem avec proposition d'opérateur de propagation d'objet :

let { [action.id]: deletedItem, ...rest } = state
return rest
34
Dan Abramov
const remove = (state, bucketId, personId) => state.map(
  bucket => bucket.id === bucketId
    ? { ...bucket, items: bucket.items.filter(person => person.id !== personId) }
    : bucket,
);

Usage:

const state = [
  {
    id: 123,
    items: [
      {
        id: 'abc',
        name: 'Kinna',
      },
      {
        id: 'def',
        name: 'Meggy',
      },
    ],
  },
  {
    id: 456,
    items: [
      {
        id: 'ghi',
        name: 'Ade',
      },
      {
        id: 'jkl',
        name: 'Tades',
      },
    ],
  },
];

console.log(remove(state, 123, 'abc'));
2
Ivan Nikitovic

j'ai résolu mon problème de cette façon

if(action.type === "REMOVE_FROM_PLAYLIST"){
        let copy = Object.assign({}, state) 
        delete copy.playlist[action.index].songs[action.indexSongs];

        return copy;
    }

j'espère que ça aide quelqu'un d'autre.

0
Dante Cervantes

Vous pouvez également utiliser la méthode omod de lodash .

Sachez que l'importation de lodash augmentera un peu votre taille de construction. Gardez le contrôle un peu en important simplement la méthode spécifique: import omit from 'lodash/omit';

Si possible, je suggère d'utiliser l'opérateur d'étalement d'objet comme décrit dans Réponse de Dan .

0
Antonio Merker

Vous pouvez utiliser le trait de soulignement . Il fait exactement ce que vous essayez de faire.

0
Cool Acid

Si vous optez pour le langage Javascript simple, le moyen le plus élégant auquel je puisse penser est d'utiliser Array.prototype.reduce pour réduire l'état:

var state = [
 { id: 123,
   items:[
           { id: 'abc',
             name: 'albert'
           }, 
           ... 
         ]
 }, 
 ... 
]

function filterOut (state) {
  return (bucketId, personId) => {
    return state.reduce((state, bucket) => {
      return state.concat(
        (bucketId === bucket.id) ?
          Object.assign({}, bucket, {items: bucket.items.filter((person) => person.id !== personId)}) :
          bucket
      );
    }, []);
  }
}

var newState = filterOut(state)(123, 'abc');
0
danielepolencic