I have this object in state
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'
},
],
},
],
and function that deletes object of array by given 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 });
}
it deletes the task containing the id, but also deletes the outer key that marks day. I can't seem to find the answer why actions nested deeply affect the outer key
Your code as it is, isn't doing what you are expecting it to do, or it does to much (eg, the unneccessary copy of the state.tasks
into updatedTasks
). This copy is not necessary, because map will already produce a new array for you, so in a sense you are copying it twice.
You are removing the outer property when you are returning
return Object.values(item).map((boxForTask) => { /*...*/ } );
as this will go only into the values of each of these properties, you don't have a clue what your properties might be afterwards.
Another interesting piece of code would be the inner map
, where you should probably use filter
(otherwise, you would have some undefined
in the resulting output). A filter
would just return the matching items, whereas map
would return all items
To update your current code, you could simply do it in the following way
function copyOfTasksWithoutId(tasks, id) {
return tasks.map(task => {
return Object.keys(task).map(key => {
return {
[key]: task[key]
.filter(taskWithId => taskWithId.id !== id)
};
});
});
}
The result will be a copy of the tasks array, with a matching outer property and the tasks that should be removed will be deleted. It will not mutate the original input, so that would fit your needs in react as well (for this reason, I also print the original array after the filtered one in the below snippet)
const 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' }, ], }, ]; function copyOfTasksWithoutId(tasks, id) { return tasks.map(task => Object.keys(task).map(key => ({ [key]: task[key] .filter(taskWithId => taskWithId.id !== id) }) ) ); } console.log(copyOfTasksWithoutId(tasks, 12234)); console.log(tasks);
Perhaps something like the following would work for you? This approach achieves the delete/filtering behaviour based on Array#reduce()
, Array#map()
and Object#entries()
:
var state = { 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' }, ], } ] }; const _deleteTask = (id) => { const tasks = state.tasks.map(task => { return Object.entries(task).reduce((t, entry) => { const dayKey = entry[0]; const dayArray = entry[1].filter(dayItem => dayItem.id !== id); t[ dayKey ] = dayArray; return t; }, {}); }); state.tasks = tasks; // this.setState({ tasks: updatedTasks }); }; console.log('Before', state); _deleteTask(12235); console.log('After', state);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.