在阅读React Cookbook时,我偶然发现了一个代码片段,当用户检查TODO列表中已完成的任务时,将调用此函数:
markAsCompleted = id => {
// Finding the task by id...
const foundTask = this.state.items.find(task => task.id === id);
// Updating the completed status...
foundTask.completed = true;
// Updating the state with the new updated task...
this.setState({
items: [
...this.state.items,
...foundTask
]
});
}
UPD:不知何故,我完全错过了foundTask上的传播算子。因此,真正发生的是状态仅通过... this.state.items(已更改)进行更新,而... foundTask部分未进入状态,因为它不是有效的传播。
乍一看,它应该将一个新元素添加到items数组中,而不是进行更新,因此我去了JS控制台进行检查:
state = { items: [{id: '0', done: false}, {id: '1', done: false}] }
upd = state.items.find(obj => obj.id === '0') // {id: "0", done: false}
upd.done = true // also updates object inside the array
state = { items: [...state.items, upd] }
/* Indeed, adds a new element:
items: Array(3)
0: {id: "0", done: true}
1: {id: "1", done: false}
2: {id: "0", done: true}
*/
因此,我下载了代码并在本地运行。而且,令我惊讶的是,它起作用了!状态正在更新,没有任何麻烦,没有多余的元素出现。我使用React DevTools在测试时查看实时状态。
我在网上搜索,但找不到类似本书的任何示例,但有更好的解释。通常,所有解决方案都涉及使用.map()构建新数组,然后替换现有数组(例如https://stackoverflow.com/a/44524507/10304479)。
我看到的书本代码片段和控制台测试之间的唯一区别是React使用的是.setState(),所以也许这可以有所帮助。任何人都可以帮助澄清,它为什么起作用?
谢谢!
Array.find将返回数组中匹配的第一个值。这里的数组由对象组成,返回的值将是对该对象的引用。
const foundTask = this.state.items.find(task => task.id === id);
此处foundTask
将引用中包含的相同对象state.items
。因此,当您进行修改时,foundTask
您将修改与中相同的对象state.items
。
例如,
如果this.state.items
是[{ id: 1 }]
,如果您这样做
const foundTask = this.state.items.find(obj => obj.id === 1);
foundTask.id = 2;
console.log(this.state.items); // [{ id:2 }]
在代码中
this.setState({
items: [
...this.state.items,
...foundTask
]
});
这将使用completed
任务的更新值来更新状态。...foundTask
将在控制台中给您一个错误,因为foundTask
它将是一个对象,并且您将其散布在一个数组中。
在这里不会...foundTask
产生相同的结果。也许没有错误。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句