【问题标题】:How to delete object from array using object property - React如何使用对象属性从数组中删除对象 - React
【发布时间】:2018-07-01 07:15:51
【问题描述】:

我有一个待办事项列表,其中包含孙子项中的删除按钮,单击该按钮时会触发父项中的事件 - 我希望此事件删除与单击的孙子项对应的数组条目。

父级(包含数组和我对该函数的尝试)

const tasks = [
  { name: 'task1', isComplete: false },
  { name: 'task2', isComplete: true },
  { name: 'task3', isComplete: false },
]

// taskToDelete is the name of the task - doesn't contain an object
deleteTask(taskToDelete) {
    this.state.tasks.remove(task => task.name === taskToDelete);
    this.setState({ tasks: this.state.tasks });

}

任何帮助将不胜感激

【问题讨论】:

  • 我会提醒您不要将删除功能仅基于名称,除非您明确阻止用户在代码中的其他位置创建多个具有相同名称的任务(如果有人需要做同样的任务 3 次,他们可能想要 3 次)。基于索引/ID 的解决方案将是一个更安全的系统使用。 deleteTask 应该只接受您尝试删除的任务的索引。
  • @jmcgriz 我将否定重复的任务,是的。

标签: javascript arrays reactjs


【解决方案1】:

有两个问题:

  1. 您似乎试图直接修改this.state.tasks。重要的是不要这样做,永远不要直接修改this.state 或上面的任何对象。请参阅the React documentation for state 中的“不要直接修改状态”

  2. 您正在将一个派生自当前状态的对象传递给setState。永远不要那样做也很重要。 :-) 相反,传递setState 一个函数并使用它在调用该函数时传递给您的状态对象。来自the documentation中的“状态更新可能是异步的”

    因为this.propsthis.state 可能会异步更新,您不应该依赖它们的值来计算下一个状态... [相反]...使用第二种形式的@ 987654329@ 接受一个函数而不是一个对象。

    (我的重点)

我认为您在数组上的remove 是假设的,但为避免疑问,数组没有remove 方法。在这种情况下,由于我们需要一个新数组,最好的办法是使用filter 删除所有不应该仍然存在的条目。

所以:

deleteTask(taskToDelete) {
    this.setState(prevState => {
        const tasks = prevState.tasks.filter(task => task.name !== taskToDelete);
        return { tasks };
    });
}

【讨论】:

  • 干得好,先生,cmets 对prevState 做了很好的宣传 :)
【解决方案2】:

你可以简单地过滤数组:

this.setState(prevState => ({
    tasks: prevState.tasks.filter(task => task.name !== 'taskToDelete')
}));

同样在基于this.state更新时,最好使用函数形式,因为setState就是async

【讨论】:

    【解决方案3】:

    您可以使用过滤器按照不可变模式从数组中删除一个对象(过滤器将创建一个新数组):

    deleteTask(taskToDelete) {
        const newTaskArray = this.state.tasks.filter(task => task.name !== taskToDelete);
        this.setState({ tasks: newTaskArray });
    
    }
    

    编辑:解决方案的代码:https://codepen.io/Dyo/pen/ZvPoYP

    【讨论】:

    • 你打错字了。
    • 如果对象基于当前状态,您不能将对象传递给setState。您必须改用函数回调样式。更多:reactjs.org/docs/state-and-lifecycle.html#using-state-correctly
    • @ArupRakshit:是的,整个“状态更新可能是异步的”部分。主要是:“因为 this.props 和 this.state 可能会异步更新,所以你不应该依赖它们的值来计算下一个状态。”
    • @T.J.Crowder 好的,你明白了,你可能是对的,我想我从来没有使用过这个,因为用例非常简单,但在复杂的应用程序上可能会出现问题。很抱歉一直坚持。
    • @Dyo:完全不用担心,希望它有用。快乐编码!
    【解决方案4】:

    你可以实现deleteTask方法如下:

    deleteTask(taskToDelete) {
      this.setState((prevState, props) => {
        const tasks = [...prevState.tasks];
        const indexOfTaskToDelete = tasks.findIndex(
          task => task.name === taskToDelete
        );
        tasks.splice(indexOfTaskToDelete, 1);
        return { tasks };
      });
    }
    

    A.找到taskToDelete的索引。

    B.然后使用splice方法从集合中删除该项目

    C.然后调用setStatetasks 更新状态。

    【讨论】:

    • 我没有。这就是我写const {tasks} = this.state;@T.J.Crowder 的原因。
    • 是的,我想了解您在这里想说什么。仍然没有任何意义。在另一个帖子中发表了相同的评论。
    • +1,很高兴它对您有所帮助,更新后的答案存在一个问题,请使用:const tasks = prevState.tasks.slice(0); 数组参考 :)
    • @MayankShukla 已修复。谢谢:)
    • 奥雅纳大修!
    【解决方案5】:

    您可以使用higher order函数Array#filter删除任务。

    let updatedTasks  =     this.state.tasks.filter(task => task.name !== taskToDelete);
    
    this.setState({ tasks: updatedTasks });
    

    【讨论】:

    • 如果对象基于当前状态,您不能将对象传递给setState。您必须改用函数回调样式。更多:reactjs.org/docs/state-and-lifecycle.html#using-state-correctly
    • @T.J.克劳德 - 为什么? setState 接受一个对象,他正在创建一个新对象,filter 创建一个新数组。当然回调版本更好,因为你知道状态是最新的,但上面是有效的(文档中使用了类似的)。
    • @T.J.Crowder 我没有直接改变状态。
    • @dashton:查看链接了解原因。不,您不会在文档中找到使用 object 调用 setState 的示例,该对象的数据是 this.state 的修改版本。
    • 我的问题是不能使用。您显然可以,但如果更新是异步的,则不应该
    【解决方案6】:

    我已按照以下步骤从状态数组中删除特定的选定对象:

    这里我使用了一个复选框列表,当我选择一个复选框时,它会将它添加到状态数组中,当它被取消选择时,它将从数组中删除。

    if (checked) {
                var tempObject = { checkboxValue: data, label: title }
                this.state.checkBoxState.push(resTemp);
            } else {
                var element = data; //data is coming from different method.
                for (let index = 0; index < this.state.checkBoxState.length; index++) {
                    if (element === this.state.checkBoxState[index].checkboxValue) {
                        this.state.checkBoxState.splice(index, 1);
                    }
                }
            }
    

    我被这个问题困住了,我正在分享我的解决方案。希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 2021-01-16
      • 2013-05-05
      • 2021-01-30
      • 2015-04-08
      • 2021-07-01
      • 2015-12-29
      • 1970-01-01
      • 1970-01-01
      • 2021-10-29
      相关资源
      最近更新 更多