Vir
Vir

Reputation: 25

Delete record from todo list in ReactJS giving error

Am learning ReactJS and building my todo application. However am facing an issue when I try to delete a task.

I have two files TodoList.js and TodoItems.js

TodoList.js

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

class TodoList extends Component {

    //Function to handle adding tasks    
    addTask(event) {
        //Get task Value
        let task = this.refs.name.value;

        //Newitem Object
        if (task !== "") {
            let newItem = {
                text: task,
                key: Date.now()
            }
            this.setState({
                items: this.state.items.concat(newItem)
            });

            this.refs.name.value = ""; //Blank out the task input box
        }
    }

    deleteItem(key) {
        var filteredItems = this.state.items.filter(function (item) {
            return (item.key !== key);
        });

        this.setState({
            items: filteredItems
        });
    }


    constructor(props) {
        super(props);

        this.state = {
            items: []
        };
        this.addTask = this.addTask.bind(this);
        this.deleteItem = this.deleteItem.bind(this);
    }
    render() {
        return (
            <div className="todoListMain">
                <div className="header">
                    <form>
                        <input placeholder="Enter Task" id="name" ref="name"></input>
                        <button type="button" onClick={this.addTask}>Add Task</button>
                    </form>
                </div>

                <div className="list">
                    <TodoItems entries={this.state.items} delete={this.deleteItem} />
                </div>
            </div>
        );
    }
}

export default TodoList;

TodoItems.js has following code

import React, {Component} from 'react';

class TodoItems extends Component {
    constructor(props) {
        super(props);
        this.state = {};
    }


    delete(key) {
        this.props.delete(key);
    }

    listTasks(item) {
        return <li key={item.key} onClick={() => this.delete(item.key)}>{item.text}</li>
    }


    render() {
        let entries = this.props.entries;
        let listItems = entries.map(this.listTasks);

        return (
            <ul className="theList">
                {listItems}
            </ul>
        );
    }
}

export default TodoItems;

I am getting an error on deleting task when clicked on it.

and I am getting error as here

I guess it means function delete is not defined but it has been defined still am getting an error. Can anyone explain how do I resolve this issue?

Upvotes: 1

Views: 100

Answers (3)

Treycos
Treycos

Reputation: 7492

You should never attempt to modify your props directly, if something in your components affects how it is rendered, put it in your state :

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

To delete your element, just filter it out of your entries array :

    delete(key) {
        this.setState(prevState => ({
            entries: prevState.entries.filter(item => item.key !== key)
        }))
    }

And now the render function :

    render() {
        const { entries } = this.state //Takes the entries out of your state

        return (
            <ul className="theList">
                {entries.map(item => <li key={item.key} onClick={this.delete(item.key)}>{item.text}</li>)}
            </ul>
        );
    }

Full code :

class TodoItems extends Component {
    constructor(props) {
        super(props);

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

    delete = key => ev => {
        this.setState(prevState => ({
            entries: prevState.entries.filter(item => item.key !== key)
        }))
    }

    render() {
        const { entries } = this.state

        return (
            <ul className="theList">
                {entries.map(item => <li key={item.key} onClick={this.delete(item.key)}>{item.text}</li>)}
            </ul>
        );
    }
}

You should also try to never use var. If you do not plan to modify a variable, use const, otherwise, use let.


EDIT : The error shown in your edit come from listTasks not being bound to your class. To solve it you can either bind it (as shown in an other answer below) or convert it in another function :

listTasks = item => {
    return <li key={item.key} onClick={() => this.delete(item.key)}>{item.text}</li>
}

Short syntax :

listTasks = ({ key, text }) => <li key={key} onClick={() => this.delete(key)}>{text}</li>

Upvotes: 1

Nino Filiu
Nino Filiu

Reputation: 18473

Replace this:

onClick={this.delete(item.key)}
// passes the result of `this.delete(item.key)` as the callback

By this:

onClick={() => this.delete(item.key)}
// triggers `this.delete(item.key)` upon click

Upvotes: 0

sn42
sn42

Reputation: 2444

Welcome to Stackoverflow!

Check this section of the React Docs. You either have to bind your class functions in the constructor or use arrow functions.

class TodoItems extends Component {
    constructor(props) {
        // ...
        this.delete = this.delete.bind(this);
    }

    delete(key) {
        this.props.delete(key);
    }

    // Or without binding explicitly:
    delete2 = (key) => {
        // ...
    }
}

Upvotes: 0

Related Questions