React Delete Button Todolist

Hello guys im having a bit of trouble with this, I have found some topics on here but none seem to be helping anyways this is my problem. I need to create a delete button as well as a delete todo method on the app components using an array of .filter, and then pass it to the ToDo component as a prop, as well as Add an onClick event listener to the delete button, and have it call deleteTodo, passing it the index of the to-do.

  import React, { Component } from 'react';
import './App.css';
import ToDo from './components/ToDo.js';
class App extends Component {
 constructor(props) {
   super(props);
   this.state = {
     todos: [
       { description: 'Walk the cat', isCompleted: true},
       { description: 'Throw away the dishes', isCompleted: false},
       { description: 'Buy new dishes', isCompleted: false}
     ],
     newTodoDescription: ''
   };
 }



 handleChange(e) {
   this.setState({ newTodoDescription: e.target.value })
 }
 handleSubmit(e) {
   e.preventDefault();
   if (!this.state.newTodoDescription) { return }
   const newTodo = { description: this.state.newTodoDescription, isCompleted: false};
   this.setState({ todos: [...this.state.todos, newTodo], newTodoDescription: ''});
 }

 toggleComplete(index) {
   const todos = this.state.todos.slice();
   const todo = todos[index];
   todo.isCompleted = todo.isCompleted ? false : true;
   this.setState({ todos: todos});
   }

    render() {
      return (
        <div className="App">
          <ul>
                    { this.state.todos.map( (todo, index) =>
              <ToDo key={ index } description={ todo.description } isCompleted={ todo.isCompleted } toggleComplete={ () => this.toggleComplete(index) } />
            )}
          </ul>
          <form onSubmit={ (e) => this.handleSubmit(e) }>
          <input type="text" value={ this.state.newTodoDescription } onChange={ (e) => this.handleChange(e) } />
          <input type="submit" />
          </form>
          </div>
      );
    }
  }


export default App;
import React, {Component} from 'react';

class ToDo extends Component {
  render() {
    return (
                <li>
                <input type="checkbox" checked={ this.props.isCompleted } onChange={ this.props.toggleComplete } />
                 <span> { this.props.description }</span>
                 </li>

    );
  }
}

export default ToDo;

Upvotes: 1

Views: 910

Answers (1)

Tholle
Tholle

Reputation: 112777

You can create a new method deleteTodo in App that takes in the todo object you want to remove and filter that out from the state.

Since the order of todos will now change, you can no longer use the array index as key for the Todo components. You can add an id to your todo objects and use that instead.

Example

class App extends React.Component {
  state = {
    todos: [
      { id: Math.random(), description: "Buy new dishes", isCompleted: false }
    ],
    newTodoDescription: ""
  };

  handleChange(e) {
    this.setState({ newTodoDescription: e.target.value });
  }

  handleSubmit(e) {
    e.preventDefault();
    if (!this.state.newTodoDescription) {
      return;
    }
    const newTodo = {
      id: Math.random(),
      description: this.state.newTodoDescription,
      isCompleted: false
    };
    this.setState({
      todos: [...this.state.todos, newTodo],
      newTodoDescription: ""
    });
  }

  toggleComplete(todo) {
    this.setState({
      todos: this.state.todos.map(t => {
        if (t !== todo) {
          return t;
        }
        return { ...t, isCompleted: !t.isCompleted };
      })
    });
  }

  deleteTodo(todo) {
    this.setState({ todos: this.state.todos.filter(t => t !== todo) });
  }

  render() {
    return (
      <div className="App">
        <ul>
          {this.state.todos.map(todo => (
            <ToDo
              key={todo.id}
              description={todo.description}
              isCompleted={todo.isCompleted}
              toggleComplete={() => this.toggleComplete(todo)}
              deleteTodo={() => this.deleteTodo(todo)}
            />
          ))}
        </ul>
        <form onSubmit={e => this.handleSubmit(e)}>
          <input
            type="text"
            value={this.state.newTodoDescription}
            onChange={e => this.handleChange(e)}
          />
          <input type="submit" />
        </form>
      </div>
    );
  }
}

class ToDo extends React.Component {
  render() {
    return (
      <li>
        <input
          type="checkbox"
          checked={this.props.isCompleted}
          onChange={this.props.toggleComplete}
        />
        <span> {this.props.description}</span>
        <button onClick={this.props.deleteTodo}>Delete</button>
      </li>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

Upvotes: 1

Related Questions