Javascript 如何在React中有条件地更新集合中项的属性?
我有一个存储在以下状态的项目集合:Javascript 如何在React中有条件地更新集合中项的属性?,javascript,reactjs,Javascript,Reactjs,我有一个存储在以下状态的项目集合: this.state = { items: [ { name: "foo", description: "a foo", index: 0 }, { name: "bar", description: "a bar", index: 1 }, { name: "herp", description: "a herp", index: 2 }, { name: "derp", descrip
this.state = {
items: [
{ name: "foo", description: "a foo", index: 0 },
{ name: "bar", description: "a bar", index: 1 },
{ name: "herp", description: "a herp", index: 2 },
{ name: "derp", description: "a derp", index: 3 }
]
};
索引
属性表示集合中每个项的顺序位置。有时我需要重新订购这些物品。例如,“derp”可能需要移到前面,因此需要更新其他项目的索引:
{ name: "derp", description: "a derp", index: 0 },
{ name: "bar", description: "a bar", index: 1 },
{ name: "herp", description: "a herp", index: 2 },
{ name: "foo", description: "a foo", index: 3 }
我目前正在使用不变性助手
包中的更新
更新状态。然而,我确信这不是正确的方法(尽管它有效):
//originalIndex是一个保存原始索引的变量
//newIndex是保存新索引的变量
//初始化UpdateItems,以便在循环中进行更新
让updateItems=update(this.state.items,{[originalIndex]:{'index':{$set:newIndex}}});
for(var i=newIndex;i
这感觉像是一次大规模的黑客攻击
我的问题是,是否可以使用条件逻辑调用update,因此可以用单个调用update来替换此循环?为什么不在render()上对项目进行排序:
为什么不在render()上对项目进行排序:
假设我们从每个项目中提取
index
属性,您可以创建如下新列表:
const items = this.state.items.slice();
const value = items[oldIndex];
items.splice(oldIndex, 1); // remove the one you want to move
items.splice(newIndex, 0, value); // add it back to the desired index
this.setState({ items });
也就是说,使用slice创建列表的(浅)副本,然后使用splice交换周围的元素
由于一次只移动一个图元,因此可以使用以下方法保存一行:
const [value] = items.splice(oldIndex, 1);
这将拼接
返回的数组的第一个元素分配给值
如果要保留索引
(为什么?),则需要重新分配索引:
this.setState({ items: items.map((item, index) => ({ ...item, index })) });
假设我们从每个项目中提取
index
属性,您可以创建如下新列表:
const items = this.state.items.slice();
const value = items[oldIndex];
items.splice(oldIndex, 1); // remove the one you want to move
items.splice(newIndex, 0, value); // add it back to the desired index
this.setState({ items });
也就是说,使用slice创建列表的(浅)副本,然后使用splice交换周围的元素
由于一次只移动一个图元,因此可以使用以下方法保存一行:
const [value] = items.splice(oldIndex, 1);
这将拼接
返回的数组的第一个元素分配给值
如果要保留索引
(为什么?),则需要重新分配索引:
this.setState({ items: items.map((item, index) => ({ ...item, index })) });
如果
index
真正指的是items数组中的索引,那么将其作为每个对象内部的属性似乎有点不太妥当。@TomFenech也这么说。当一个元素可以被它在数组中的索引直接引用时,在数组中不需要index属性,这实际上是一个很好的观点!我没有想到这一点。因此,如果我们删除索引
属性,那么每个项目是否仍然是一个具有名称
属性的对象,或者您现在只是一个字符串列表?@TomFenech每个项目仍然是一个对象。事实上,我只是根据你的回答更新了这个问题。很明显,我把问题简化得太多了。我的实际对象除了索引外还包含4个属性。index
作为每个对象内部的属性似乎有点不太妥当,如果它真正指的是items数组中的索引。与@TomFenech所说的一样。当一个元素可以被它在数组中的索引直接引用时,在数组中不需要index属性,这实际上是一个很好的观点!我没有想到这一点。因此,如果我们删除索引
属性,那么每个项目是否仍然是一个具有名称
属性的对象,或者您现在只是一个字符串列表?@TomFenech每个项目仍然是一个对象。事实上,我只是根据你的回答更新了这个问题。很明显,我把问题简化得太多了。除了索引之外,我的实际对象还包含4个属性。因为JavaScript的排序
修改了它的接收者,所以此代码将变异此.state
,React文档强烈警告不要这样做。您可能需要执行让toDisplay=this.state.items.slice().sort(…)
来操作数组的副本。因为JavaScript的排序
修改了它的接收器,所以此代码将变异this.state
,React文档强烈警告不要这样做。您可能需要执行让toDisplay=this.state.items.slice().sort(…)
来操作数组的副本。谢谢Tom。我同意事后看来,在对象中包含索引是毫无意义的。明天我来试试。谢谢汤姆。我同意事后看来,在对象中包含索引是毫无意义的。我明天给你打一针。