如何从 Immutable 中的数组中删除对象?
How to remove an object from an array in 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
returns -1
,那是 delete
的有效值。
您可以使用 Array#filter
.
return state.set('things', state.get('things').filter(o => o.get('id') !== 'a1'));
或者,就像你一样"searching and then deleting"...
var itemIndex = this.state.get("tracks").findIndex(x => x.get('id') === 'a2');
return itemIndex > -1 ? this.state.deleteIn(["tracks", itemIndex]) : this.state;
这将确保状态在没有变化时不会发生变化。
在寻找类似任务的解决方案时发现此线程。
用update方法解决:
return state.update('things', (things) => things.filter((t) => t.id !== action.things.id))
任何 idea/comment 哪一个是 better/preferred?
当您使用过滤器时,它会迭代所有循环 -> 一种有效的方法是查找索引 => 切片并使用拆分器...
const index = state.findIndex(data => data.id === action.id);
return [...state.slice(0, index), ...state.slice(index + 1)];
即使没有 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
}
ImmutableJS 使用嵌套数组
Immutablejs 很棒,但同时在某些边缘情况下会使事情变得更加复杂,尤其是在使用嵌套数组时。
对于这个特定问题,有时更容易将其返回到一般意义上的 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 } }})
不幸的是,第3步需要专门设置为undefined
,因为如果您直接将myList
设置为数组值,ImmutableJS将在当前列表之间进行值比较并仅修改他们创造了奇怪的行为。
这样做的理由是为了简化心理开销。我不建议在循环中这样做,如果必须但应该在循环中操作纯 JS 数组在第 3 步之前。
给定这样的状态:
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
returns -1
,那是 delete
的有效值。
您可以使用 Array#filter
.
return state.set('things', state.get('things').filter(o => o.get('id') !== 'a1'));
或者,就像你一样"searching and then deleting"...
var itemIndex = this.state.get("tracks").findIndex(x => x.get('id') === 'a2');
return itemIndex > -1 ? this.state.deleteIn(["tracks", itemIndex]) : this.state;
这将确保状态在没有变化时不会发生变化。
在寻找类似任务的解决方案时发现此线程。 用update方法解决:
return state.update('things', (things) => things.filter((t) => t.id !== action.things.id))
任何 idea/comment 哪一个是 better/preferred?
当您使用过滤器时,它会迭代所有循环 -> 一种有效的方法是查找索引 => 切片并使用拆分器...
const index = state.findIndex(data => data.id === action.id);
return [...state.slice(0, index), ...state.slice(index + 1)];
即使没有 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
}
ImmutableJS 使用嵌套数组
Immutablejs 很棒,但同时在某些边缘情况下会使事情变得更加复杂,尤其是在使用嵌套数组时。
对于这个特定问题,有时更容易将其返回到一般意义上的 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 } }})
不幸的是,第3步需要专门设置为undefined
,因为如果您直接将myList
设置为数组值,ImmutableJS将在当前列表之间进行值比较并仅修改他们创造了奇怪的行为。
这样做的理由是为了简化心理开销。我不建议在循环中这样做,如果必须但应该在循环中操作纯 JS 数组在第 3 步之前。