# Building an Awesome Todo List App

**URL:** <https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214>\
**Category:** programming\
**Created:** [March 20, 2017, 3:22am UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214 "2017-03-20T03:22:50Z")\
**Posts on this page:** 20\
**Page:** 4

<div class="post-metadata">

**Author:** ![dannyhz](https://avatars.discourse-cdn.com/v4/letter/d/50afbb/32.png) [@dannyhz](https://forum.kirupa.com/u/dannyhz)\
**Post date:** [June 29, 2018, 11:32pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/62 "2018-06-29T23:32:17Z")

</div>

Nevermind, I got the remove items functioning right. I just had to change some errors I made on the declaration of the props and it worked!

---

<div class="post-metadata">

**Author:** ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)\
**Post date:** [June 30, 2018, 5:17am UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/63 "2018-06-30T05:17:40Z")

</div>

Those errors can be tricky to identify and fix. Glad you got it sorted out 🙂

---

<div class="post-metadata">

**Author:** ![Minimin](https://avatars.discourse-cdn.com/v4/letter/m/977dab/32.png) [@Minimin](https://forum.kirupa.com/u/Minimin)\
**Post date:** [August 9, 2018, 5:33pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/64 "2018-08-09T17:33:20Z")

</div>

Need help pls. I followed through with the tutorial but encountered the following issue:

 ![image](https://canada1.discourse-cdn.com/flex011/uploads/kirupa/original/2X/b/bc2b520a77bbc60909d376d2b2b096245efe1960.png)

I have checked that the delete props are defined. In my TodoList, I already have:  
this.addItem = this.addItem.bind(this);  
this.deleteItem = this.deleteItem.bind(this);

---

<div class="post-metadata">

**Author:** ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)\
**Post date:** [August 9, 2018, 6:10pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/65 "2018-08-09T18:10:46Z")

</div>

Can you post your full code? I’m curious to know what is going on in more detail 🙂

---

<div class="post-metadata">

**Author:** ![Minimin](https://avatars.discourse-cdn.com/v4/letter/m/977dab/32.png) [@Minimin](https://forum.kirupa.com/u/Minimin)\
**Post date:** [August 9, 2018, 6:30pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/66 "2018-08-09T18:30:27Z")

</div>

Hi kirupa,  
Thanks for the quick response! Here’s my full code:

**TodoItems.js** :

```auto
import React, { Component } from "react";
 
class TodoItems extends Component {

  constructor(props) {
    super(props);
    this.delete = this.delete.bind(this);
  }

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

  createTasks(item) {
    return <li onClick={() => this.delete(item.key)} 
    key={item.key}>{item.text}</li>
  }
 
  render() {
    var todoEntries = this.props.entries;
    var listItems = todoEntries.map(this.createTasks);
 
    return (
      <ul className="theList">
          {listItems}
      </ul>
    );
  }
};
 
export default TodoItems;

```

**TodoList.js:**

```auto
import React, { Component } from "react";
import TodoItems from "./TodoItems";
import "./TodoList.css";
 
class TodoList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      items: []
    };
    this.addItem = this.addItem.bind(this);
    this.deleteItem = this.deleteItem.bind(this);
  }
  addItem(e) {
    if (this._inputElement.value !== "") {
      var newItem = {
        text: this._inputElement.value,
        key: Date.now()
      };
   
      this.setState((prevState) => {
        return { 
          items: prevState.items.concat(newItem) 
        };
      });
      this._inputElement.value = "";
    }
     
    console.log(this.state.items);
       
    e.preventDefault();
  }

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

  render() {
    return (
      <div className="todoListMain">
        <div className="header">
          <form onSubmit={this.addItem}>
            <input ref={(a) => this._inputElement = a} placeholder="enter task">
            </input>
            <button type="submit">add</button>
          </form>
        </div>
        <TodoItems entries={this.state.items} delete={this.deleteItem}/>
      </div>
    );
  }
}
 
export default TodoList;

```

---

<div class="post-metadata">

**Author:** ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)\
**Post date:** [August 9, 2018, 6:33pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/67 "2018-08-09T18:33:26Z")

</div>

Your code is being treated as formatting by the response, so lines are getting swallowed up. Can you paste your code, highlight it, and hit the \</\> code formatting button? 🙂

It is the fifth button from the left when composing a message:

 ![image](https://canada1.discourse-cdn.com/flex011/uploads/kirupa/original/2X/c/c529699c8aa1d051e1bf03d827062f245decec07.png)

EDIT: Nevermind! You made the change as I was composing this haha. Taking a look.

---

<div class="post-metadata">

**Author:** ![Minimin](https://avatars.discourse-cdn.com/v4/letter/m/977dab/32.png) [@Minimin](https://forum.kirupa.com/u/Minimin)\
**Post date:** [August 9, 2018, 6:40pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/68 "2018-08-09T18:40:28Z")

</div>

Ok… Here it is… 🙂

**TodoItems.js:**

```
import React, { Component } from "react";
 
class TodoItems extends Component {

  constructor(props) {
    super(props);
    this.delete = this.delete.bind(this);
  }

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

  createTasks(item) {
    return <li onClick={() => this.delete(item.key)} 
    key={item.key}>{item.text}</li>
  }
 
  render() {
    var todoEntries = this.props.entries;
    var listItems = todoEntries.map(this.createTasks);
 
    return (
      <ul className="theList">
          {listItems}
      </ul>
    );
  }
};
 
export default TodoItems;

```

**TodoList.js**

```
import React, { Component } from "react";
import TodoItems from "./TodoItems";
import "./TodoList.css";
 
class TodoList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      items: []
    };
    this.addItem = this.addItem.bind(this);
    this.deleteItem = this.deleteItem.bind(this);
  }
  addItem(e) {
    if (this._inputElement.value !== "") {
      var newItem = {
        text: this._inputElement.value,
        key: Date.now()
      };
   
      this.setState((prevState) => {
        return { 
          items: prevState.items.concat(newItem) 
        };
      });
      this._inputElement.value = "";
    }
     
    console.log(this.state.items);
       
    e.preventDefault();
  }

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

  render() {
    return (
      <div className="todoListMain">
        <div className="header">
          <form onSubmit={this.addItem}>
            <input ref={(a) => this._inputElement = a} placeholder="enter task">
            </input>
            <button type="submit">add</button>
          </form>
        </div>
        <TodoItems entries={this.state.items} delete={this.deleteItem}/>
      </div>
    );
  }
}
 
export default TodoList;
```

---

<div class="post-metadata">

**Author:** ![Minimin](https://avatars.discourse-cdn.com/v4/letter/m/977dab/32.png) [@Minimin](https://forum.kirupa.com/u/Minimin)\
**Post date:** [August 9, 2018, 6:50pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/69 "2018-08-09T18:50:52Z")

</div>

Hi Kirupa,  
I think I found the reason for the error:  
Under TodoItem.js, I should change this

```
  constructor(props) {
    super(props);
    this.delete = this.delete.bind(this);

```

to

```
constructor(props) {
super(props);
this.createTasks = this.createTasks.bind(this);

```

Thanks so much for looking into this 😄

---

<div class="post-metadata">

**Author:** ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)\
**Post date:** [August 9, 2018, 6:58pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/70 "2018-08-09T18:58:24Z")

</div>

Your timing is scarily good haha. I was about to post the same thing. I have updated the tutorial to mention this. The version on Github also has the correct line of code: [https://github.com/kirupa/kirupa/blob/master/reactjs/todolist/src/TodoItems.js](https://github.com/kirupa/kirupa/blob/master/reactjs/todolist/src/TodoItems.js)

---

<div class="post-metadata">

**Author:** ![zaid\_afzal](https://avatars.discourse-cdn.com/v4/letter/z/71c47a/32.png) [@zaid\_afzal](https://forum.kirupa.com/u/zaid_afzal)\
**Post date:** [October 18, 2018, 2:37pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/71 "2018-10-18T14:37:42Z")

</div>

![Untitled](https://canada1.discourse-cdn.com/flex011/uploads/kirupa/original/2X/0/03ab046b5c72c07f6b918f6bafd22c6e6ae2d218.png)

---

<div class="post-metadata">

**Author:** ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)\
**Post date:** [October 18, 2018, 9:07pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/72 "2018-10-18T21:07:40Z")

</div>

Can you share your code?

---

<div class="post-metadata">

**Author:** ![theorios](https://avatars.discourse-cdn.com/v4/letter/t/96bed5/32.png) [@theorios](https://forum.kirupa.com/u/theorios)\
**Post date:** [November 25, 2018, 5:31pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/73 "2018-11-25T17:31:10Z")

</div>

Nice tutorial @kirupa. Thanks a lot!

I have a question. Let’s say that onClick of li item, instead of deleting it, i would like to show the text in input, change it and when i hit add to update this specific item. How would i do this?

---

<div class="post-metadata">

**Author:** ![hoddy](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/hoddy/32/8311_2.png) [@hoddy](https://forum.kirupa.com/u/hoddy)\
**Post date:** [March 21, 2017, 5:18pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/75 "2017-03-21T17:18:49Z")

</div>

could you please explain the javascript syntax of the ref tag used on the input element of the TodoList component. thanks

`ref={(a) => this._inputElement = a}`

---

<div class="post-metadata">

**Author:** ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)\
**Post date:** [March 21, 2017, 8:05pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/76 "2017-03-21T20:05:52Z")

</div>

It is using an ES6 feature known as arrow functions that is a shorthand way of writing the following:

```
(function (a) {
  return this._inputElement = a;
});

```

The end result is that the referenced element is assigned to the `_inputElement` property.

The Mozilla documentation is a good place to learn more about it: [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow\_functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)

I also recorded a short video in case that helps: [https://www.youtube.com/watch?v=Sh-NYbDcUug](https://www.youtube.com/watch?v=Sh-NYbDcUug)

🙂

---

<div class="post-metadata">

**Author:** ![CriticalMAS](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/criticalmas/32/8340_2.png) [@CriticalMAS](https://forum.kirupa.com/u/CriticalMAS)\
**Post date:** [April 2, 2017, 2:53am UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/77 "2017-04-02T02:53:17Z")

</div>

Do you have a demo page for the Todo List?

I can’t get mine to work. I get “items not defined”.

> **[notepad.pw](https://notepad.pw/share/u1n5n06h7)**
>
> Save your notes online for free and share them with friends!

thank you

---

<div class="post-metadata">

**Author:** ![kirupa](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/kirupa/32/11616_2.png) [@kirupa](https://forum.kirupa.com/u/kirupa)\
**Post date:** [April 2, 2017, 4:06pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/78 "2017-04-02T16:06:27Z")

</div>

Here you go: [https://www.kirupa.com/react/examples/todo.htm](https://www.kirupa.com/react/examples/todo.htm) 🙂

---

<div class="post-metadata">

**Author:** ![kreaton](https://avatars.discourse-cdn.com/v4/letter/k/c5a1d2/32.png) [@kreaton](https://forum.kirupa.com/u/kreaton)\
**Post date:** [April 10, 2017, 7:25am UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/79 "2017-04-10T07:25:27Z")

</div>

Thanks a lot 🙂

---

<div class="post-metadata">

**Author:** ![askeladde](https://avatars.discourse-cdn.com/v4/letter/a/e56c9b/32.png) [@askeladde](https://forum.kirupa.com/u/askeladde)\
**Post date:** [June 24, 2017, 5:01pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/80 "2017-06-24T17:01:39Z")

</div>

I’m still confused about the use of the “ref” property and the purpose of the callback.

ref={(a) =\> this.\_inputElement = a}

I understand that it equals the code below.

(function (a) {  
return this.\_inputElement = a;  
});

But, what’s the purpose of returning this.inputElement. What does “this” refer to and what is “a”?

---

<div class="post-metadata">

**Author:** ![Elizabeth\_Amanda](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/elizabeth_amanda/32/8778_2.png) [@Elizabeth\_Amanda](https://forum.kirupa.com/u/Elizabeth_Amanda)\
**Post date:** [November 9, 2017, 3:15am UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/81 "2017-11-09T03:15:42Z")

</div>

Hi Kirupa,

I have another question for you 😀  
This evening I completed the Todo List, and I think I understand most of it.  
I’m trying build upon it, and make a wish list app.

It looks like this, for right now.

 ![07 PM](https://canada1.discourse-cdn.com/flex011/uploads/kirupa/original/2X/2/2bd75c497f1fe257d63ebe3401f217ca4569c822.png)

The only thing is I’m having a hard time figuring out how to get these in the list to display. I thought I could:

```
<input ref={(a) => this._inputElement = a}
   placeholder="item">
</input>
<input ref={(b) => this._inputElement = b}
   placeholder="description">
</input>
<input ref={(c) => this._inputElement = c}
    placeholder="link">
</input>

```

But nothing is happening.

I know you’re probably busy, but if you have a chance, could help point me where in the code I could get this to work?

---

<div class="post-metadata">

**Author:** ![senocular](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/senocular/32/7217_2.png) [@senocular](https://forum.kirupa.com/u/senocular)\
**Post date:** [November 9, 2017, 1:36pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/82 "2017-11-09T13:36:57Z")

</div>

@Elizabeth_Amanda,

Generally you want to avoid using `ref` if you can. The problem with your example is that you have 3 inputs and each one has a ref which assigns itself to the same instance property, `_inputElement`. So instead of having references to 3 different inputs, you have one reference that gets assigned a different input reference 3 different times - whose value will be the last input reference assigned to it. In fact it looks like you tried to fix this by changing the reference variable, but that’s not the one that makes a difference (`a`, `b`, and `c`). That can be the same for each, its the `_inputElement` that you’d want to be different.

But again, using `ref` isn’t preferred and can be avoided. So instead, set input `value`s to state properties and detect changes with `onChange`. You just need to make sure you have properties for each of your inputs. Here’s an example: [https://jsfiddle.net/v4qvt8bk/](https://jsfiddle.net/v4qvt8bk/)

[Previous page](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214.md?page=3)

[Next page](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214.md?page=5)
