为什么这个表达式只覆盖数组中的其他属性?
const toggleComplete = (id) => {
const updatedTodos = todos.map((todo) =>
todo.id === id ? todo.completed = !todo.completed : todo
);
setTodos(updatedTodos);
}
字符串
使用前面的代码,todos数组只包含完成的字段,并删除所有其他字段。
const toggleComplete = (id) => {
const updatedTodos = todos.map((todo) => {
if (todo.id === id) {
todo.completed = !todo.completed;
}
return todo;
});
setTodos(updatedTodos);
}
型
而使用此代码,所有数组字段保持不变,只更改已完成的字段,这是预期的行为。
3条答案
按热度按时间b1zrtrql1#
.map()
的结果完全基于回调函数 * 返回的内容。在第二个例子中,它总是返回todo
对象。但在第一个例子中,它返回了这个:字符串
这有条件地返回整个
todo
对象或以下表达式的结果:型
赋值表达式的结果是被赋值的值,并且只有该值。因此,当这个表达式执行一个修改
todo
对象的赋值时,这没有什么影响,因为该对象没有返回,所以.map()
不会将其用于任何事情。它只使用返回值。这让人想起
.map()
操作的常见 * 误用 *。它的意思是将一个数组 * 投影 * 到一个新数组中,它 * 不是 * 用于循环数组以修改该数组中的某些内容。.forEach()
或简单的for
循环将用于此。顺便说一句我建议不要像这样在React中使用 either 方法。虽然这是创建一个新数组来设置状态,但在这样做之前,它也是 mutating 状态。
根本不要在
todo
上分配属性。相反,从.map()
回调返回一个新对象:型
oknrviil2#
让我根据你预期的输出来更正第一个代码,然后它将是不言自明的,
字符串
如果你还是不明白,下面是解释:当你在胖箭头函数中不提供花括号时,它将简单地返回你写的表达式的结果(在你的例子中,它将始终是
true
),所以它正在替换数组中的对象。在第二部分中,您切换
todo.completed
,然后返回todo
,所以它工作正常。jtoj6r0c3#
因为在第一个代码中,如果'todo.id'与'id'相同,则实际上返回'todo.completed'。在一个代码示例中,您基本上是使用三元运算符来执行此操作:
字符串
您可能需要阅读有关三元运算符https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_operator的信息