web-dev-qa-db-ja.com

Immutableの配列からオブジェクトを削除する方法は?

このような状態が与えられた場合:

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

ID「a1」が削除された新しい状態を作成するにはどうすればよいですか?新しいアイテムをプッシュするのは簡単です:

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

しかし、idプロパティによってオブジェクトを検索して削除する方法がわかりません。私はこれを試しました:

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

しかし、面倒であるように見えます。さらに、findIndex-1を返す場合、それはdeleteの有効な値であるため、アイテムが見つかった場合にのみ機能します。

24
ffxsam

Array#filter

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

フィルタを使用している場合、すべてのサイクルを繰り返します-> 1つの効果的な方法は、インデックス=>スライスを見つけてスプリッタを使用することです...

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

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

または、「検索してから削除する」ため...

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

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

これにより、変更がない場合に状態が変化しないことが保証されます。

4
hazardous

ネストされた配列を操作するImmutableJS

Immutablejsは素晴らしいですが、同時にいくつかのEdgeのケースでは事態をより複雑にします特にネストされた配列を扱う場合

この特定の問題について、一般的な意味でJSに戻す方が簡単な場合があります。

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

残念なことに、単にundefinedを配列値として直接設定すると、ImmutableJSは現在のリスト間の値の比較を行い、それらを変更するだけで奇妙なものになるため、ステップ3はmyListに特に設定する必要があります動作。

これはメンタルオーバーヘッドを単純化するための正当化です。ループでこれを行うことはお勧めしません。むしろ、手順3の前でなければならない場合、ループで純粋なJS配列を操作します。

0
Jason Sebring

同様のタスクの解決策を探しているときに、このスレッドを見つけました。 pdate メソッドで解決しました:

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

より良い/好まれるアイデア/コメントはありますか?

0

Immutable.jsがなくても、次の関数でそれを行うことができます。

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