Javascript 从状态删除对象将删除父对象的键
我有这个物体处于状态Javascript 从状态删除对象将删除父对象的键,javascript,reactjs,Javascript,Reactjs,我有这个物体处于状态 tasks: [ { 'Day 1': [ { id: 1234, task: 'Task 1', created: 'somedate' }, {
tasks: [
{
'Day 1': [
{
id: 1234,
task: 'Task 1',
created: 'somedate'
},
{
id: 1235,
task: 'Task 2',
created: 'somedate'
},
{
id: 1225,
task: 'Task 3',
created: 'somedate'
}
],
},
{
'Day 2': [
{
id: 12234,
task: 'Task 4',
created: 'somedate'
},
{
id: 12235,
task: 'Task 5',
created: 'somedate'
},
],
},
],
和按给定id删除数组对象的函数
_deleteTask = (id) => {
const tasks = [...this.state.tasks];
const updatedTasks = tasks.map((item) =>
{ return Object.values(item).map((boxForTask) => {
return Object.values(boxForTask).map((eachTaskBox => {
if (eachTaskBox.id !== id) return eachTaskBox
}));
})}
);
this.setState({ tasks: updatedTasks });
}
它删除包含id的任务,但也删除标记日期的外键。我似乎找不到答案,为什么嵌套的操作会对外键产生深刻影响您的代码本身没有做您期望它做的事情,或者它做了很多事情(例如,将
状态.tasks
的不必要副本复制到updatetask
)。这个拷贝是不必要的,因为map已经为您生成了一个新的数组,所以在某种意义上,您要拷贝它两次
返回时正在删除外部属性
return Object.values(item).map((boxForTask) => { /*...*/ } );
因为这只会涉及到这些属性中的每一个的值,所以您不知道以后您的属性可能是什么
另一段有趣的代码是内部映射
,您可能应该在其中使用过滤器
(否则,结果输出中会有一些未定义的
)。filter
将只返回匹配的项目,而map
将返回所有项目
要更新您当前的代码,您可以简单地按照以下方式进行
function copyOfTasksWithoutId(tasks, id) {
return tasks.map(task => {
return Object.keys(task).map(key => {
return {
[key]: task[key]
.filter(taskWithId => taskWithId.id !== id)
};
});
});
}
结果将是任务数组的副本,具有匹配的外部属性,并且应该删除的任务将被删除。它不会改变原始输入,因此也能满足您在react中的需要(因此,我也会在下面代码段中过滤后打印原始数组)
const任务=[{
“第一天”:[{
身份证号码:1234,
任务:“任务1”,
创建:“somedate”
},
{
身份证号码:1235,
任务:“任务2”,
创建:“somedate”
},
{
身份证号码:1225,
任务:“任务3”,
创建:“somedate”
}
],
},
{
“第二天”:[{
身份证号码:12234,
任务:“任务4”,
创建:“somedate”
},
{
身份证号码:12235,
任务:“任务5”,
创建:“somedate”
},
],
},
];
函数copyoftaskswithout id(任务,id){
返回tasks.map(任务=>Object.keys(任务).map(键=>({
[键]:任务[键]
.filter(taskWithId=>taskWithId.id!==id)
})
)
);
}
log(copyOfTasksWithoutId(tasks,12234));
console.log(任务)代码>也许下面这样的东西适合你?这种方法实现了基于Array#reduce()
、Array#map()
和Object#entries()的删除/过滤行为:
var state={任务:[
{
“第一天”:[
{
身份证号码:1234,
任务:“任务1”,
创建:“somedate”
},
{
身份证号码:1235,
任务:“任务2”,
创建:“somedate”
},
{
身份证号码:1225,
任务:“任务3”,
创建:“somedate”
}
],
},
{
“第二天”:[
{
身份证号码:12234,
任务:“任务4”,
创建:“somedate”
},
{
身份证号码:12235,
任务:“任务5”,
创建:“somedate”
},
],
}
]
};
常量删除任务=(id)=>{
const tasks=state.tasks.map(task=>{
返回Object.entries(任务).reduce((t,entry)=>{
const dayKey=条目[0];
const dayArray=条目[1]。筛选器(dayItem=>dayItem.id!==id);
t[dayKey]=dayArray;
返回t;
}, {});
});
state.tasks=任务;
//this.setState({tasks:updatetasks});
};
console.log('Before',state);
_删除任务(12235);
console.log('After',state)
看起来内部映射更像是一个过滤器(因为您似乎只在它与给定的id
不同时才返回它)。外键消失的原因是因为您正在返回Object.values(item).map
,所以本质上,您循环所有属性,并且只返回值。我个人认为没有必要扩展数组,因为您映射了所有的updatedTasks
已经是一个完整的副本,map
s的预期返回值是一个对象,但您返回的是一个数组(映射的object.values
array)。如果您完全控制了数据结构,如果通过扩展数组([…this.state.tasks]
),将动态属性名{Day 1':[…]}
更改为静态属性名{name:'Day 1',tasks:[…]}
,您可能会认为您在复制数组,那么从逻辑上解决这些类型的问题就变得容易多了。实际上,您只是在复制数组。您需要对阵列进行深度复制,以便精确克隆阵列。否则,将复制更深嵌套对象的引用,而不是实际值。我知道
是可选的,但每次我看不到它们时,它都会让我感到厌烦:)很公平<代码>代码>添加-如果我遗漏了任何内容,请告诉我:-)很明显,您以前没有遗漏任何内容,这只是我个人的观点:)您建议对象。条目而不是地图的原因是什么?(既然你问了,_deleteTask的const声明缺少一个;
):DThanks-如果性能不是一个大问题,我倾向于以这种方式使用对象.entries
,这样核心的删除/过滤工作就可以在对象.entries
回调的范围内完成,而不是依赖于上下文数据的这种逻辑(即task
)这是通过周围的闭包“传入”的。谢谢!这正是我需要的解释,现在我头脑中的混乱越来越清楚了