it-swarm.com.de

Wie entferne ich ein Objekt aus einem Array in Immutable?

In einem Zustand wie diesem:

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

Wie kann ich einen neuen Status erstellen, in dem die ID "a1" entfernt wird? Es ist leicht genug, neue Elemente zu pushen:

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

Ich kann jedoch nicht herausfinden, wie ein Objekt anhand seiner id-Eigenschaft gesucht und entfernt werden kann. Ich habe das versucht:

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

Aber es scheint chaotisch zu sein, und es funktioniert nur, wenn das Element gefunden wird. Wenn findIndex-1 zurückgibt, ist dies ein gültiger Wert für delete.

22
ffxsam

Sie können Array#filter verwenden.

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

Wenn Sie einen Filter verwenden, durchläuft er alle Zyklen -> Eine effektive Methode ist das Finden des Index => Slice und die Verwendung des Splitters ...

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

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

Alternativ, wie Sie "suchen und dann löschen" ...

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

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

Dadurch wird sichergestellt, dass der Zustand nicht verändert wird, wenn keine Änderungen vorliegen.

3
hazardous

ImmutableJS, das mit verschachtelten Arrays arbeitet

Immutablejs ist großartig, macht jedoch in einigen Edge-Fällen die Dinge komplizierter, insbesondere beim Arbeiten mit verschachtelten Arrays.

Manchmal ist es einfacher, JS im Allgemeinen für diese spezielle Angelegenheit zu verwenden.

// 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 } }})

Leider ist Schritt 3 erforderlich, um speziell auf undefined zu setzen. Wenn Sie myList einfach direkt als Array-Wert festlegen, führt ImmutableJS einen Vergleich der Werte zwischen der aktuellen Liste durch und ändert sie nur, wodurch ein seltsames Verhalten erzeugt wird.

Die Begründung dafür ist, den mentalen Overhead zu vereinfachen. Ich empfehle Ihnen nicht, dies in einer Schleife zu tun, sondern manipulieren Sie das reine JS-Array in einer Schleife, wenn Sie dies vor Schritt 3 tun sollten.

0
Jason Sebring

Diesen Thread gefunden, während nach einer Lösung für eine ähnliche Aufgabe gesucht wurde . Mit der Methode update gelöst:

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

welche idee/kommentar welche ist besser/bevorzugt?

0

Das geht auch ohne immutable.js mit folgender Funktion.

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