简体   繁体   English

如何在 React 中删除 ToDo 项 onClick?

[英]How to delete a ToDo Item onClick in React?

I'm doing a simple todo app with React, just to practise.我正在用 React 做一个简单的待办事项应用程序,只是为了练习。 How can I delete a list item, when clicking on it?单击列表项时如何删除它?

Here is my todos.js这是我的 todos.js

export default class Todos extends Component {
    constructor(props) {
        super(props);
        this.state = { todos: [], text: '' };
    }

    addTodo(e) {
        e.preventDefault();
        this.setState({ todos: [ this.state.text, ...this.state.todos ] });
        this.setState({ text: ''});
    }

    updateValue(e) {
        this.setState({ text: [e.target.value]})
    }

    render() {
        return(
            <div>
                <form onSubmit = {(e) => this.addTodo(e)}>
                    <input
                        placeholder="Add Todo"
                        value={this.state.text}
                        onChange={(e) => {this.updateValue(e)}}
                    />
                    <button type="submit">Add Todo</button>
                </form>
                <TodoList todos={this.state.todos}/>
            </div>
        );
    }
}

And here is the TodoList.js, where I'm trying to remove a list item from.这是 TodoList.js,我试图从中删除列表项。

import React, { Component } from 'react';
import { connect } from 'react-redux';

export default class TodoList extends Component {
    removeItem(e) {
        // splice this.props.todos??
    }
    render() {
        return(
            <ul>
                { this.props.todos.map((todo) => {
                    return <li onClick={(e) => { this.removeItem(e)}} key={todo}>{ todo }</li>
                })}
            </ul>
        );
    }
}

To delete the todo items, first pass a function from parent component:要删除待办事项,首先从父组件传递一个函数:

<TodoList todos={this.state.todos} removeTodo={this.removeTodo}/>

Bind this function in the constructor :constructor函数中绑定这个函数:

this.removeTodo = this.removeTodo.bind(this);

Define this function in parent component, it will delete that item from state variable:在父组件中定义此函数,它将从state变量中删除该项目:

removeTodo(name){
    this.setState({
        todo: this.state.todo.filter(el => el !== name)
    })
}

Then inside child component call this method to delete todo:然后在子组件内部调用此方法删除待办事项:

export default class TodoList extends Component {
    removeItem(e) {
        this.props.removeTodo(item);
    }
    render() {
        return(
            <ul>
                { this.props.todos.map((todo) => {
                    return <li onClick={() => { this.removeItem(todo)}} key={todo}>{ todo }</li>
                })}
            </ul>
        );
    }
}

Suggestion:建议:

Don't call setState multiple time within a function if you want to set multiple state values then write it like this:如果要设置多个state值,请不要在function内多次调用setState然后像这样编写:

this.setState({
    a: value1,
    b: value2,
    c: value3
})

Working example:工作示例:

 class Todos extends React.Component { constructor(props) { super(props); this.state = { todos: [], text: '' }; this.removeTodo = this.removeTodo.bind(this); } addTodo(e) { e.preventDefault(); this.setState({ todos: [ this.state.text, ...this.state.todos ], text: '' }); } removeTodo(name, i){ let todos = this.state.todos.slice(); todos.splice(i, 1); this.setState({ todos }); } updateValue(e) { this.setState({ text: e.target.value}) } render() { return( <div> <form onSubmit = {(e) => this.addTodo(e)}> <input placeholder="Add Todo" value={this.state.text} onChange={(e) => {this.updateValue(e)}} /> <button type="submit">Add Todo</button> </form> <TodoList todos={this.state.todos} removeTodo={this.removeTodo}/> </div> ); } } class TodoList extends React.Component { removeItem(item, i) { this.props.removeTodo(item, i); } render() { return( <ul> { this.props.todos.map((todo,i) => { return <li onClick={() => { this.removeItem(todo, i)}} key={i}>{ todo }</li> })} </ul> ); } } ReactDOM.render(<Todos/>, document.getElementById('app'))
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id='app'/>

Update:更新:

This is for @whs.bsmith doubt, the code that i suggested will work properly in the case where user will add the unique items in the todo list, if he will try to add the same item it will not reflect in ui because OP is using the todo items name as the key and key should be unique.这是@whs.bsmith 的疑问,我建议的代码将在用户将在待办事项列表中添加唯一项目的情况下正常工作,如果他尝试添加相同的项目,它将不会反映在 ui 中,因为 OP 是使用待办事项名称作为键,键应该是唯一的。

To solve that issue:要解决这个问题:

In working snippet i used indexes in place of todo items name for key, that will work properly and it will allow the user to add same item multiple times and on deletion, it will delete only that specific item not all the item having that same name, But it's not a good idea to use indexes as the key.在工作片段中,我使用索引代替待办事项名称作为键,这将正常工作,它将允许用户多次添加相同的项目,并且在删除时,它只会删除该特定项目,而不是所有具有相同名称的项目,但是使用索引作为key并不是一个好主意。

You have called setState two times in the addTodo function.您已经在addTodo函数中调用了setState两次。 You can set todos and text in a single setState function like this:您可以在单个 setState 函数中设置待办事项文本,如下所示:

addTodo(e) {
    e.preventDefault();
    this.setState({ todos: [ this.state.text, ...this.state.todos ], text: '' });
}

Do not write removeItem function in TodoList Component as it is purely working on props.不要在TodoList组件中编写removeItem函数,因为它纯粹是在处理道具。 Pass a removeItem function from Todos to it and remove that item in Todos's removeItem function like this:将一个removeItem函数从Todos传递给它,并在 Todos 的 removeItem 函数中删除该项目,如下所示:

import React, {Component} from 'react'
export default class Todos extends Component {
  constructor(props) {
    super(props);
    this.state = { todos: [], text: '' };
    this.removeItem = this.removeItem.bind(this)
  }

  addTodo(e) {
    e.preventDefault();
    this.setState({ todos: [ this.state.text, ...this.state.todos ], text: '' });
  }


  updateValue(e) {
    this.setState({ text: [e.target.value]})
  }
  removeItem(index) {
    const todos = this.state.todos.filter((todo, todoIndex) => {
      return todoIndex !== index
    })
    this.setState({ todos })
  }
  render() {
    return(
      <div>
        <form onSubmit = {(e) => this.addTodo(e)}>
          <input
            placeholder="Add Todo"
            value={this.state.text}
            onChange={(e) => {this.updateValue(e)}}
            />
          <button type="submit">Add Todo</button>
        </form>
        <TodoList todos={this.state.todos} removeItem={this.removeItem} />
      </div>
    );
  }
}

class TodoList extends Component {
  render() {
    return(
      <ul>
        { this.props.todos.map((todo, index) => {
          return <li onClick={(e) => { this.props.removeItem(index)}} key={todo}>{ todo }</li>
        })}
      </ul>
    );
  }
}

Hope, it helps.希望能帮助到你。

class TodoList extend React.Component{
    constructor(props){
        super(props);
        this.state = {
            todos: [],
            todo: ''
        }
        this.changeTodo = this.changeTodo.bind(this);
        this.addTodo = this.addTodo.bind(this);
        this.removeTodo = this.removeTodo.bind(this);
    }

    changeTodo(event){
        this.setState({
            todo: event.target.value
        })
    }

    addTodo(){
        let { todo, todos } = this.state;
        this.setState({
            todo: '',
            todos: [...todos, todo]
        })
    }

    removeTodo(index){
        let { todos } = this.state;
        todos.splice(index, 1);
        this.setState({
            todos: todos
        })
    }

    render(){
        let { todo, todos } = this.state;
        return <div>
            <input value={todo} onChange={this.changeTodo}/>
            <button onClick={this.addTodo}>Add Todo</button>
            {
                todos.map((todo, index)=>{
                    return <h1 onClick={this.removeTodo.bind(undefined, index)} key={index}>{todo}</h1>
                })
            }
        </div>
    }
}

This is a small example for TodoList.这是 TodoList 的一个小例子。 Go through this code to understand remove todo in your TodoList app.通过此代码了解在您的 TodoList 应用程序中删除待办事项。

Only thing to do is to move todos to state in TodoList and pass the index of the current todo in to the removeItem method.唯一能做的是将todosstateTodoList ,并通过当前待办事项的索引到removeItem方法。 Then splice it as you suggested.然后按照你的建议拼接。

In TodoList :TodoList

constructor(props) {
    super(props);

    this.state = { todos: props.todos };
}

removeItem(index) {
    this.setState({
        todos: this.state.todos.filter((_, i) => i !== index)
    });
}

render() {
    return(
        <ul>
            { this.state.todos.map((todo, index) => {
                return <li onClick={(e) => { this.removeItem(index)}} key={todo}>{ todo }</li>
            })}
        </ul>
    );
}

Remove item courtesy of Removing element from array in component state删除项目礼貌从组件状态的数组中删除元素

First, you would want the removeItem method to exist in the Todos class, since that is where that state is stored.首先,您希望在 Todos 类中存在 removeItem 方法,因为这是存储状态的地方。 Then, you can either use filter or slice然后,您可以使用过滤器或切片

export default class Todos extends Component {
    constructor(props) {
        super(props);
        this.state = { todos: [], text: '' };
    }

    addTodo(e) {
        e.preventDefault();
        this.setState({ todos: [ this.state.text, ...this.state.todos ] });
        this.setState({ text: ''});
    }

    updateValue(e) {
        this.setState({ text: [e.target.value]})
    }

    removeItem = index => {
        //either use filter
        const { todos } = this.state;
        const newTodos = todos.filter((todo, i) => i !== index);
        this.setState({ todos: newTodos});

        //or use slice
        const slicedNewTodos = todos.slice(0, index).concat(todos.slice(index + 1));
        this.setState({ todos: slicedNewTodos});
    }

    render() {
        return(
            <div>
                <form onSubmit = {(e) => this.addTodo(e)}>
                    <input
                        placeholder="Add Todo"
                        value={this.state.text}
                        onChange={(e) => {this.updateValue(e)}}
                    />
                    <button type="submit">Add Todo</button>
                </form>
                <TodoList removeItem={this.removeItem} todos={this.state.todos}/>
            </div>
        );
    }
}

import React, { Component } from 'react';
import { connect } from 'react-redux';

class TodoList extends Component {
    render() {
        return(
            <ul>
                { this.props.todos.map((todo, index) => {
                    return <li onClick={() => this.props.removeItem(index)} key={todo}>{ todo }</li>
                })}
            </ul>
        );
    }
}

Everyone has given a good big picture overview.每个人都给出了一个很好的大局概述。 I find this to be a good way to delete the todo from the todolist我发现这是从待办事项列表中删除待办事项的好方法

todolist.splice(index, 1); todolist.splice(index, 1);

Splice removes 1 element from the startIndex of index (in the todolist array) Splice 从 index 的 startIndex 中移除 1 个元素(在 todolist 数组中)

We can set a flag for the todo data and on initializing that data we can set the flag as true and when we delete the todo list we can set the flag as false.我们可以为待办事项数据设置一个标志,在初始化该数据时,我们可以将标志设置为 true,当我们删除待办事项列表时,我们可以将标志设置为 false。 Please refer the below code.请参考以下代码。

const TodoComponent = ({ dataArray }) => {

  const [todos, setTodos] = useState(dataArray)

  // initial loading of todo items.
  useEffect(() =>{
    if (dataArray.length) {
      dataArray.forEach(todo =>{
        todo.show = true
      })
      setTodos(dataArray)
    }
  }, [dataArray])

 // Close the todo Item.
  const closeTodoItem = (todo, index) =>{
    todo.show = false
    todos[index] = todo
    setTodos([...todos])
  }

  return (
    todos.filter(todo => todo.show === true).length >0  &&
    (
      <Col span={24} className={style.todoBg} style={compStyle}>
        {todos.map((todo,index) => (
          (todo.show && (
            <Col span={24} className={style.todo}>
              <Col className={style.todoInner}>
                <p> {todo.content} </p>
              </Col>
              <Icon onClick={() => closeTodoItem(todo, index)} className={style.close}>close</Icon>
            </Col>
          ))
        ))}
      </Col>
    )
  )}

The above approach worked for me.上述方法对我有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM