var index = list.findIndex(item => item.name === "three")
list = list.setIn([index, "count"], 4)
说明
更新Immutable.js集合始终会返回这些集合的新版本,不会改变原始版本。因此,我们不能使用JavaScript的list[2].count = 4
变异语法。相反,我们需要调用方法,就像我们可能会对Java集合类做的那样。
让我们从一个更简单的例子开始:只有列表中的计数。
var arr = [];
arr.push(2);
arr.push(1);
arr.push(2);
arr.push(1);
var counts = Immutable.List.of(arr);
现在如果我们想要更新第三个项目,一个普通的JS数组可能会是这样:counts[2] = 4
。由于我们不能使用突变,并且需要调用方法,因此我们可以使用counts.set(2, 4)
- 这意味着在索引2
处设置值4
。
深度更新
但你提供的示例有嵌套数据。我们不能只对初始集合使用set()
。
Immutable.js集合具有名称以"In"结尾的一系列方法,允许您在嵌套集合中进行更深入的更改。大多数常见的更新方法都有相关的"In"方法。例如,对于set
,有setIn
。这些"In"方法不接受索引或键作为第一个参数,而是接受一个“键路径”。键路径是一个索引或键的数组,说明如何到达要更新的值。
在你的示例中,你想要更新列表中索引为2的项目,然后更新该项目内键为“count”的值。因此,键路径将是[2,“count”]
。 setIn
方法的第二个参数与set
完全相同,它是我们要放置的新值,所以:
list = list.setIn([2, "count"], 4)
寻找正确的键路径
更进一步地,你实际上说你想要更新的项目是名称为"three"的项目,这与仅仅是第三个项目不同。例如,也许你的列表没有排序,或者之前删除了名为 "two" 的项?这意味着首先我们需要确保我们知道正确的键路径!为此,我们可以使用findIndex()
方法(顺便说一下,它几乎与Array#findIndex完全相同)。
一旦我们在列表中找到了要更新的项目的索引,我们可以提供到我们希望更新的值的键路径:
var index = list.findIndex(item => item.name === "three")
list = list.setIn([index, "count"], 4)
NB: Set
vs Update
这个问题提到了更新方法而不是设置方法。我将解释该函数中的第二个参数(称为updater
),因为它与set()
不同。虽然set()
的第二个参数是我们想要的新值,但是update()
的第二个参数是一个接受先前值并返回我们想要的新值的函数。然后,updateIn()
是update()
的“In”变体,它接受一个键路径。
例如,假设我们想要一个你的示例的变体,不仅将计数设置为4
,而且还将现有计数增加1,我们可以提供一个添加1到现有值的函数:
var index = list.findIndex(item => item.name === "three")
list = list.updateIn([index, "count"], value => value + 1)