从React数组中删除元素

3
我如何在React中从数组中删除一个项目?我尝试了几个方法,但都没有成功。只是想制作一个基本的待办事项应用程序。我更新了我的帖子,以提供渲染方法来展示deleteTodo的去向。我还更新了我的deleteTodo,使用了我从这篇文章中得到的答案。它有点起作用,唯一的问题是它删除了待办列表中的所有项目,而不仅仅是单个项目。
class App extends Component {
  state = {
    inputValue: "",
    todos: [{
        value: "walk the dog",
        done: false
      },
      {
        value: "do the dishes",
        done: false
      }
    ]
  }

  addTodo = (e) => {
    this.setState({
      inputValue: e.target.value
    });
  }

  handleSubmit = (e) => {
    e.preventDefault();
    // console.log('clicked')
    const newTodo = {
      value: this.state.inputValue,
      done: false
    }
    const todos = this.state.todos;
    todos.push(newTodo);
    this.setState({
      todos,
      inputValue: ''
    })
  }

  deleteTodo = (value) => {
    // Take copy of current todos
    const todos = [this.state.todos];
    const filteredTodos = todos.filter((item) => item.value !== value);
    this.setState({
      todos: filteredTodos
    }) 
  }

  render() {
    return (
      <div className="App">
        <Form 
          addTodo={this.addTodo}
          handleSubmit={this.handleSubmit}
        />
        <List 
         todos={this.state.todos}
         deleteTodo={this.deleteTodo}
        />
      </div>
    );
  }
}

export default App;

1
在使用 filter 时,您必须返回 true 或 false。https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/filter - divine
你可能会发现MDN文档中的filter在这里很有用。 - Michael Elliott
deleteTodo() 函数中:尝试使用 const todos = [...this.state.todos]。查看 Spread Syntax 获取更多信息。 - Arman Charan
3个回答

0

你使用的filter似乎是问题所在。如果要使用filter创建一个新的不包含value元素的数组,可以尝试以下方法:

编辑:更新了完整的工作演示答案。

import React, {Component} from 'react';
import './App.css';

class Form extends Component {
    constructor(props) {
        super(props);
        this.textRef = React.createRef();
    }

    render() {
        return (
            <form onSubmit={(e)=>{e.preventDefault(); this.props.handleSubmit(this.textRef.current.value)}}>
                <input type="text" ref={this.textRef}/>
                <input type="submit" value="add"/>
            </form>
        );
    }
}

class List extends Component {
    render() {
        return (
            <ul>
                {
                    this.props.todos.map((todo) => (
                        <li key={todo.value}>
                            <p><input type="checkbox" checked={todo.done}/>{todo.value} </p>
                            <input type="button" onClick={() => (this.props.deleteTodo(todo.value))} value="delete"/>
                        </li>
                    ))
                }
            </ul>
        );
    }
}

class App extends Component {
    state = {
        inputValue: "",
        todos: [{
            value: "walk the dog",
            done: false
        },
            {
                value: "do the dishes",
                done: false
            }
        ]
    }

    addTodo = (e) => {
        this.setState({
            inputValue: e.target.value
        });
    }

    handleSubmit = (value) => {
        const newTodo = {
            value,
            done: false
        }
        const todos = [...this.state.todos];
        todos.push(newTodo);
        this.setState({
            todos,
            inputValue: ''
        })
    }

    deleteTodo = (value) => {
        const todos = this.state.todos;
        const filteredTodos = todos.filter((item) => item.value !== value);
        this.setState({
            todos: filteredTodos
        })
    }

    render() {
        return (
            <div className="App">
                <Form
                    addTodo={this.addTodo}
                    handleSubmit={this.handleSubmit}
                />
                <List
                    todos={this.state.todos}
                    deleteTodo={this.deleteTodo}
                />
            </div>
        );
    }
}


export default App;

另外,我修改了你的handleSubmit方法,以创建一个新的数组,以符合React的函数式范例。


我似乎仍然无法删除待办事项。我回去确认它是否与我的按钮连接,它是有效的,但不幸的是解决方案仍然没有做任何事情。 - Joe Escobedo
请问您能否更新问题,包括渲染方法,以便我们可以看到事件如何绑定到该方法和传递给该函数的值?您能否在deleteTodo方法中添加console.log,并打印value的值并检查它是否正常传递? - Chirag Ravindra
我试图更新这篇文章,但是格式要求太麻烦了,我无法弄清楚哪里出了问题。 - Joe Escobedo
放心地把代码贴上来吧...有人可以编辑以修复格式。我通常会将代码复制粘贴到我的IDE(我使用VScode)中,全选后运行格式化程序,按Tab键缩进4个空格,然后将其复制粘贴回SO。 - Chirag Ravindra
更新了它。我猜它想让我添加一个更长的描述。 - Joe Escobedo
你发布的那部分看起来还不错。我猜最终还是要看这些方法在 FormList 组件内部如何被调用。我已经更新了我的代码,展示了这些方法的实现示例。希望能有所帮助。 - Chirag Ravindra

0

你只需要从数组中过滤出该值,并将新的过滤后的数组设置在 setState 中。

deleteTodo = (value) => {
    // Take copy of current todos
    const todos = [...this.state.todos];
    const filteredTodos = todos.filter( (item) => item.value !== value);
  this.setState({
  todos: filteredTodos

}) }


我在这方面有所进展,唯一的问题是这个解决方案会删除整个列表而不仅仅是一个项目。 - Joe Escobedo
你能否在jsfiddle上创建一个工作的演示,并分享链接?我可以直接修复并与您分享解决方案。 - Kalpesh Singh
我可以尝试。我有多个组件,但它们给了我很多错误,而这些错误在我的编辑器中并没有出现。 - Joe Escobedo
你在这里说的是性能吗? - Kalpesh Singh

0

我已经使用了Lodash来完成这个任务。 Lodash是一个用于执行此类操作的库https://lodash.com/

如果您可以获取插入时相同的值对象,那么添加其余部分就非常容易了。

在删除函数中,您可以使用Lodash来查找数组中包含该对象的索引。

const todos = this.state.todos;
const itemToRemove = {value: "walk the dog",done: false};
var index = _.findIndex(todos, itemToRemove); 
const filteredTodos = todos.splice(index, 1)

this.setState({
  todos: filteredTodos
}) 

希望这能有所帮助


不幸的是,此解决方案中的Array.prototype.splice()改变 this.state并且仅返回itemToRemove(而不是filteredTodos)。 - Arman Charan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接