从状态中删除对象会删除父对象的键

时间:2018-11-11 23:10:48

标签: javascript reactjs

我有这个状态的物体

 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的任务,但也删除标记为day的外键。我似乎找不到答案,为什么嵌套的动作会深深地影响外键

2 个答案:

答案 0 :(得分:1)

您的代码实际上没有按照您的期望做,或者做了很多(例如,将state.tasks不必要地复制到updatedTasks中)。此副本不是必需的,因为map已经为您生成了一个新数组,因此在某种意义上您将其复制了两次。

您将在返回时删除外部属性

return Object.values(item).map((boxForTask) => { /*...*/ } );

由于这只会涉及到每个属性的值,因此您不知道之后的属性是什么。

另一段有趣的代码是内部map,您可能应该在其中使用filter(否则,输出结果中将有一些undefined)。 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)
      };
    });
  });
}

结果将是task数组的副本,具有匹配的外部属性,应删除的任务将被删除。它不会更改原始输入,因此也可以满足您的反应需求(因此,我也在下面的代码段中过滤出原始数组后打印了原始数组)

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);

答案 1 :(得分:1)

也许以下内容对您有用?这种方法基于Array#reduce()Array#map()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);