Cody Lemons
Cody Lemons

Reputation: 15

I'm having problems creating a functioning "delete button" in my react todo app

I'm brand new to Reactjs and I'm working on my first app, a todo app of course. However, everything was going smoothly until I was asked to create a delete button to remove my todos. I'm stuck and have been puzzled over this for almost 3 days. Any help or advice would be appreciated.

react-to-do/src/App.js

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 the dishes away", isCompleted: false },
        { description: "Buy new dishes", isCompleted: false }
      ],
      newTodoDescription: ""
    };
    this.deleteTodo = this.deleteTodo.bind(this);
  }

  deleteTodo(description) {
    this.setState({
      todos: this.state.todos.filter(
        (todos, index) => todos.description !== description
      )
    });
  }

  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;

react-to-do/src/ToDo.js

import React, { Component } from "react";

class ToDo extends Component {
  deleteToDo(description) {
    this.props.deleteToDo(description);
  }

  render() {
    return (
      <div className="wrapper">
        <button
          className="deleteToDo"
          onClick={e => this.deleteToDo(this.props.description)}
        >
          Delete
        </button>
        {this.props.deleteToDo}

        <li>
          <input
            type="checkbox"
            checked={this.props.isCompleted}
            onChange={this.props.toggleComplete}
          />
          <span>{this.props.description}</span>
        </li>
      </div>
    );
  }
}

export default ToDo;

react-to-do/src/index.js

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import registerServiceWorker from "./registerServiceWorker";

ReactDOM.render(<App />, document.getElementById("root"));
registerServiceWorker();

Upvotes: 0

Views: 164

Answers (2)

Prakash Kandel
Prakash Kandel

Reputation: 1043

Your code should look like

class ToDo extends React.Component {
        deleteToDo(description) {
          this.props.deleteToDo(description);
        }
          render() {
            return (
              <div className="wrapper">

              <button className="deleteToDo" onClick = {(e) => 
                  this.deleteToDo(this.props.description)}>Delete</button> 
                  {() => this.props.deleteToDo(this.props.description)}

              <li>
                <input type="checkbox" checked={ this.props.isCompleted } 
        onChange={ this.props.toggleComplete } />
                <span>{ this.props.description }</span>
              </li>
              </div>
            );
          }
        }

    class App extends React.Component {
          constructor(props) {
            super(props);
            this.state = {
              todos: [
          { description: 'Walk the cat', isCompleted: true },
          { description: 'Throw the dishes away', isCompleted: false },
          { description: 'Buy new dishes', isCompleted: false }
              ],
              newTodoDescription: ''
            };
              this.deleteTodo = this.deleteTodo.bind(this);
          }
          deleteTodo(description) {
          const filteredTodos = this.state.todos.filter((todo, index) =>  todo.description !== description);
            this.setState({
              todos: filteredTodos
            });
          }

          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) } deleteToDo={this.deleteTodo} />
                  )}
                </ul>
                <form onSubmit={ (e) => this.handleSubmit(e) }>
                  <input type="text" value={ 
                    this.state.newTodoDescription } onChange={ (e) => 
                    this.handleChange(e) } />
                  <input type="submit" />
                </form>
              </div>
            );
          }
        }

Here you forgot to pass props from App and description parameter from ToDo component.

Try here https://jsfiddle.net/prakashk/69z2wepo/101369/#&togetherjs=B3l5GDzo8A

Upvotes: 1

Shanon Jackson
Shanon Jackson

Reputation: 6581

You never pass your "deleteTodo" function as a prop to your "toDo" component. change the portion where you create you're todo components in that map to resemble something like this...

map.... => <toDo deleteToDo={this.deleteTodo}......... />

remember components are scoped to themselves if you want to call a function that exists in the parents context in a child, a reference of that function must be passed to that child as a prop.

Upvotes: 1

Related Questions