web-dev-qa-db-fra.com

Comment supprimer un objet d'un tableau dans Immutable?

Étant donné un état comme celui-ci:

state = {
  things: [
    { id: 'a1', name: 'thing 1' },
    { id: 'a2', name: 'thing 2' },
  ],
};

Comment créer un nouvel état où l'ID "a1" est supprimé? Il est assez facile de pousser de nouveaux articles:

return state.set(state.get('things').Push(newThing));

Mais je ne peux pas comprendre comment rechercher et supprimer un objet à l'aide de sa propriété id. J'ai essayé ceci:

return state.set('tracks',
  state.get('tracks').delete(
    state.get('tracks').findIndex(x => x.get('id') === 'a2')
  )
)

Mais cela semble compliqué et ne fonctionne que si l'élément est trouvé, car si findIndex renvoie -1, il s'agit d'une valeur valide pour delete.

22
ffxsam

Vous pouvez utiliser Array#filter .

return state.set('things', state.get('things').filter(o => o.get('id') !== 'a1'));
31
Tushar

Lorsque vous utilisez le filtre, il répète tous les cycles -> une méthode efficace consiste à rechercher index => slice et à utiliser le séparateur ...

const index = state.findIndex(data => data.id === action.id);

return [...state.slice(0, index), ...state.slice(index + 1)];
8
Musa

Sinon, lorsque vous "recherchez, puis supprimez" ...

var itemIndex = this.state.get("tracks").findIndex(x => x.get('id') === 'a2');

return itemIndex > -1 ? this.state.deleteIn(["tracks", itemIndex]) : this.state;

Cela garantira que l'état n'est pas muté lorsqu'il n'y a pas de changement.

3
hazardous

ImmutableJS travaillant avec des tableaux imbriqués

Immutablej est excellent, mais complique les choses dans certains cas Edge, particulièrement lorsque vous travaillez avec des tableaux imbriqués.

Parfois, il est plus facile de revenir à JS dans un sens général pour cette question particulière.

// 1. get a copy of the list into normal JavaScript
const myList = state.getIn(['root', 'someMap', 'myList']).toJS()

// 2. remove item in list using normal JavaScript and/or anything else
myList.splice(deleteIndex, 1)

// 3. return the new state based on mutated myList
return state
  .mergeDeep({ root: { someMap: { myList: undefined } }})
  .mergeDeep({ root: { someMap: { myList } }})

Malheureusement, l'étape 3 est nécessaire pour définir spécifiquement undefined car si vous définissez simplement myList directement comme valeur de tableau, ImmutableJS effectuera une comparaison des valeurs entre la liste actuelle et ne les modifiera que par un comportement étrange.

_ {La justification en est de simplifier la surcharge mentale. Je ne recommande pas de faire cela dans une boucle, mais de manipuler le tableau JS pur dans une boucle si vous devez mais devez être avant l'étape 3.

0
Jason Sebring

Vous avez trouvé ce fil en cherchant une solution à une tâche similaire . Le résolu avec update method:

return state.update('things', (things) => things.filter((t) => t.id !== action.things.id))

aucune idée/commentaire lequel est le mieux/préféré?

0
Roman Krayovskyy

Vous pouvez le faire même sans immutable.js avec la fonction suivante.

function arrayFilter(array, filter) {
  let ret = array
  let removed = 0
  for (let index = 0; index < array.length; index++) {
    const passed = filter(array[index], index, array)
    if (!passed) {
      ret = [...ret.slice(0, index - removed), ...ret.slice(index - removed + 1)]
      removed++
    }
  }
  return ret
}
0
pravdomil