javascript - 如何在不改变数组的情况下更新此状态?
问题描述
我想知道如何在以下情况下不改变状态:
我正在使用 React Hooks。我有一个TodoList
列表TodoItems
。TodoItems
可以单击以运行一个调用toggle
其completed
属性的函数。
import React, { useState } from "react";
import TodoItem from "./TodoItem";
export default function TodoList() {
const [todos, setTodos] = useState([
{ text: "Example", completed: false }
]);
const toggle = index => {
const newTodos = [...todos];
newTodos[index].completed = !newTodos[index].completed; // Mutating state?
setTodos(newTodos);
};
return (
<>
{todos.map((item, index) => (
<TodoItem key={index} index={index} todo={item} toggle={toggle} />
))}
</>
);
}
有人告诉我这是变异状态:
你创建了一个 todos 数组的副本,但你仍然改变了数组中的一个项目:
newTodos[index].completed = !newTodos[index].completed;
扩展数组只会创建数组的浅表副本,但原始 todo 对象不会被复制,因此会发生变异。
那么,在不改变状态的情况下处理这个问题的正确方法是什么?我试过传入一个prevTodos
参数,但是状态没有更新:
const toggle = index => {
setTodos(prevTodos => {
prevTodos[index].completed = !prevTodos[index].completed;
return prevTodos;
});
};
更新:我看过你们都推荐的帖子。这是一个解决方案,尽管我想知道是否有更简洁的方式来表达它:
const toggle = index => {
setTodos(
todos.map((todo, i) =>
i === index ? { ...todo, completed: !todo.completed } : todo
)
);
};
更新2:谢谢大家。我在下面发布了解决方案。StackOverflow 不会让我接受它 2 天,但我会这样做。建议帖子上接受的答案建议使用第三方库,并且它不使用 React Hooks,所以我不认为这个问题是重复的。
解决方案
找到了解决方案。map
将返回一个不同的数组,您可以收听 index 参数(在下面的代码段中,这是i
)来收听当前索引并更改您的目标对象。
const toggle = index => {
setTodos(
todos.map((todo, i) =>
i === index ? { ...todo, completed: !todo.completed } : todo
)
);
};
这些线程帮助我将其拼凑在一起:
感谢所有帮助过的人。
推荐阅读
- reactjs - 如何将类组件表转换为功能组件
- java - 将 GIF 文件保存到存储器
- kotlin - 为 Kotlin Multiplatform 项目设置 gradle 和项目结构
- java - 蓝牙适配器 getAddress() 返回 02:00:00:00:00:00
- json - Mockito Junit jupiter api没有解析参数JsonObject
- javascript - 如何在 React JS 中的 select 元素中对元素进行分组?
- ssis - Visual Studio 2019 新项目不包括 SSIS,已安装
- amazon-web-services - 如何通过 DynamoDB-Athena 连接器在查询中使用 AWS Glue 元数据
- node.js - Express / React - 在生产中,我的 axios 请求包含我的 index.html 文件作为响应,并且没有到达我的 express 服务器 api 路由
- json - Angular:将 2D json 对象转换为 XML