# 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:** 6

<div class="post-metadata">

**Author:** ![Chandra\_Kiran](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/chandra_kiran/32/12458_2.png) [@Chandra\_Kiran](https://forum.kirupa.com/u/Chandra_Kiran)\
**Post date:** [September 14, 2020, 8:16pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/104 "2020-09-14T20:16:37Z")

</div>

Hi Kirupa,  
Just wanted to check with you if we could use the event deligation here. We have added the event listener to the ‘li’. Could you please let me know how we can do that by adding the event listener to the ‘ul’ and then do the event delegation. Is it even the right way to do it?  
Thanks,  
Chandra

---

<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:** [September 15, 2020, 3:32am UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/105 "2020-09-15T03:32:23Z")

</div>

With React, the event delegation is done automatically for you. Even if you create event handlers on each element, the listening happens at the document level. That is why you don’t have to make this extra step in React. For regular JS, it is usually a good idea to delegate event handling to a common parent 🙂

---

<div class="post-metadata">

**Author:** ![jersoe](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/jersoe/32/13253_2.png) [@jersoe](https://forum.kirupa.com/u/jersoe)\
**Post date:** [January 4, 2021, 1:10pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/107 "2021-01-04T13:10:51Z")

</div>

Thanks for the tutorial. Instead of

```
this.functionName = this.functionName.bind(this);
 
functionName() {
//...
}

```

it looks easier to me to just use an arrow function. So:

```
functionName = () => {
//...
}

```

Is there a reason to use traditional functions and the bind method instead? Both seem to work.

---

<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:** [January 7, 2021, 3:52pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/108 "2021-01-07T15:52:19Z")

</div>

You are right in that an arrow function would be more concise. There isn’t a right or wrong way, but I think I will revise this content in the future to just use arrow functions.

I wrote a bit about this here: [React, Class Syntax, and Autobinding Shenanigans!](http://forum.kirupa.com/t/react-class-syntax-and-autobinding-shenanigans/637147)

---

<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:** [January 7, 2021, 5:22pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/109 "2021-01-07T17:22:20Z")

</div>

@jersoe You might also be interested in reading [Arrow Functions in Class Properties Might Not Be As Great As We Think](https://medium.com/@charpeni/arrow-functions-in-class-properties-might-not-be-as-great-as-we-think-3b3551c440b1) which talks about some of the differences and why using arrow functions isn’t always a good thing.

---

<div class="post-metadata">

**Author:** ![ksanders](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/ksanders/32/14736_2.png) [@ksanders](https://forum.kirupa.com/u/ksanders)\
**Post date:** [June 20, 2021, 12:54am UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/110 "2021-06-20T00:54:17Z")

</div>

I tried to redo the Todo List App with functional components today. The one problem that I have is that the component is not refreshed after the submit method (addItem) is called. So the items do not get shown from the TodoItems component. I am not sure what I did wrong or missed.

---

<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 20, 2021, 3:50pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/111 "2021-06-20T15:50:44Z")

</div>

Hi @ksanders - can you share your code? It’s hard to know what may be going on there 🙂

---

<div class="post-metadata">

**Author:** ![ksanders](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/ksanders/32/14736_2.png) [@ksanders](https://forum.kirupa.com/u/ksanders)\
**Post date:** [June 20, 2021, 5:33pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/112 "2021-06-20T17:33:23Z")

</div>

Yes. This is my version of the TodoList.js using functional components. I have also included the TodoItems.js as reference. It is using a class component as you did in the tutorial. I have not converted it yet.

```
import React, { useState, useRef } from 'react'
import TodoItems from './TodoItems'

const TodoList = () => {
  const [items, setItems] = useState([])

  const inputElement = useRef(null)

  const handleSubmit = (e) => {
    e.preventDefault()
    const itemArray = items
    if (inputElement.current.value !== '') {
      itemArray.unshift({
        text: inputElement.current.value,
        key: Date.now()
      })

      setItems(itemArray)
      inputElement.current.value = ''
    }

    console.log('handleSubmit', itemArray)
    console.log('items', items)
  }

  return (
    <div className='todoListMain'>
      <div className='header'>
        <form onSubmit={handleSubmit}>
          <input ref={inputElement} placeholder='enter task'></input>
          <input type='submit' value='add'/>
        </form>
      </div>
      <TodoItems entries={items} />
    </div>
  )
}

export default TodoList

import React, { Component } from 'react'
import FlipMove from 'react-flip-move';

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

    this.createTasks = this.createTasks.bind(this)
  }

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

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

  render() {
    const { entries } = this.props
    console.log('Inside TodoItems', entries)
    var listItems = entries.map(this.createTasks)

      return (
        <ul className='theList'>
          <FlipMove duration={250} easing='ease-out'>
            {listItems}
          </FlipMove>
        </ul>
      )
  }
}

export default TodoItems
```

---

<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 21, 2021, 6:03am UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/113 "2021-06-21T06:03:34Z")

</div>

Thanks for the code! Does your `items` array contain an accurate list of the tasks added? If you add a `console.log` call to `createTasks` in `TodoItems`, does it get called for each task added as well?

---

<div class="post-metadata">

**Author:** ![ksanders](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/ksanders/32/14736_2.png) [@ksanders](https://forum.kirupa.com/u/ksanders)\
**Post date:** [June 22, 2021, 12:17am UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/114 "2021-06-22T00:17:16Z")

</div>

Yes sir. I just verified that that the items array in the state does have the accurate list each time I add a new task. I added a console.log() in the createTasks call in TodoItems, but it never gets called when I add a task. It is as if the TodoList component is not refreshing on submit.

---

<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 22, 2021, 4:14pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/115 "2021-06-22T16:14:45Z")

</div>

This is a bit puzzling. Can you replace `<TodoItems entries={items} />` with `<TodoItems entries={setItems(items)} />`

Does that make the example work?

---

<div class="post-metadata">

**Author:** ![nishaanth\_vikram](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/nishaanth_vikram/32/15085_2.png) [@nishaanth\_vikram](https://forum.kirupa.com/u/nishaanth_vikram)\
**Post date:** [August 10, 2021, 8:12am UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/116 "2021-08-10T08:12:49Z")

</div>

Hello kirupa, why do we need to bind createTasks function, as this function doesnt use any React state?  
`class TodoItems extends Component {`

` ` `constructor(props) {`

` ` `super` `(props);`

` ` `this` `.createTasks = ` `this` `.createTasks.bind(` `this` `);`

` ` `}`  
`createTasks(item) {`

` ` `return` `<li onClick={() => ` `this` `.` `delete` `(item.key)} `

` ` `key={item.key}>{item.text}</li>`

`}`

---

<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 11, 2021, 3:50pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/117 "2021-08-11T15:50:55Z")

</div>

Hi @nishaanth_vikram - you are right. If it works without the binding, then it is just an oversight on my part. Something for me to revise in a subsequent edition 🙂

---

<div class="post-metadata">

**Author:** ![Sanbu94](https://avatars.discourse-cdn.com/v4/letter/s/bbe5ce/32.png) [@Sanbu94](https://forum.kirupa.com/u/Sanbu94)\
**Post date:** [December 16, 2021, 11:15am UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/119 "2021-12-16T11:15:04Z")

</div>

Hi Kirupa! Thank you for the awesome tutorial 🙂 I am however having trouble getting the ul list to show. When I type a task and press “add” the entire page goes blank.

" TypeError: todoEntries.map is not a function. (In ‘todoEntries.map(this.createTasks)’, ‘todoEntries.map’ is undefined) " This is the error code I get.

---

<div class="post-metadata">

**Author:** ![Sanbu94](https://avatars.discourse-cdn.com/v4/letter/s/bbe5ce/32.png) [@Sanbu94](https://forum.kirupa.com/u/Sanbu94)\
**Post date:** [December 16, 2021, 11:17am UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/120 "2021-12-16T11:17:12Z")

</div>

## ![Screenshot 2021-12-16 at 13.16.04](https://canada1.discourse-cdn.com/flex011/uploads/kirupa/original/3X/d/3/d34afec6383d167f722896fff6cd4947af6035f7.png) here is my code in TodoItems.js

And my Todo.js

```auto
import React, { Component } from "react";
import TodoItems from "./TodoItems";
import "./index.css";

class TODO 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,
        key: Date.now(),
      };

      this.setState((prevState) => {
        return {
          items: prevState.items.toString(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 TODO;

```

---

<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:** [December 17, 2021, 5:15am UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/121 "2021-12-17T05:15:53Z")

</div>

Hi @Sanbu94! Welcome to the forums 🙂

When you do a `console.log` on `this.props.entries` in the `render()` in **TodoItems.js** , do you see anything printed?

---

<div class="post-metadata">

**Author:** ![Sanbu94](https://avatars.discourse-cdn.com/v4/letter/s/bbe5ce/32.png) [@Sanbu94](https://forum.kirupa.com/u/Sanbu94)\
**Post date:** [December 17, 2021, 10:01am UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/122 "2021-12-17T10:01:54Z")

</div>

Hi @kirupa , thanks for the quick reply! 🙂 I get this in the console 🤔

 ![Screenshot 2021-12-17 at 11.59.40](https://canada1.discourse-cdn.com/flex011/uploads/kirupa/original/3X/e/c/ecff4a1b0d4f43a743c6871edb2120cc06193ee3.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:** [December 17, 2021, 6:10pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/123 "2021-12-17T18:10:24Z")

</div>

This is very strange! The type of `this.props.entries` is correctly set to be an Array. The error you are seeing typically happens when `map` is being called on something that isn’t Array-like.

Just for kicks, can you replace the `var todoEntries` line with this:

```auto
var todoEntries = Array.from(this.props.entries);

```

---

<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:** [December 17, 2021, 6:50pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/124 "2021-12-17T18:50:45Z")

</div>

> [@Sanbu94](#):
>
> `items: prevState.items.toString(newItem),`

This seems like a culprit. You’re setting items to a toString of the prevState items. Doing this means its no longer an array, rather a string.

---

<div class="post-metadata">

**Author:** ![Sanbu94](https://avatars.discourse-cdn.com/v4/letter/s/bbe5ce/32.png) [@Sanbu94](https://forum.kirupa.com/u/Sanbu94)\
**Post date:** [December 17, 2021, 8:28pm UTC](https://forum.kirupa.com/t/building-an-awesome-todo-list-app/636214/125 "2021-12-17T20:28:03Z")

</div>

This addition now works somewhat 🙂 Now after when I press “add” the page does not disappear and this is what is shown at console after one input. But somehow I still don’t get it to show the list of added items 🤔

 ![Screenshot 2021-12-17 at 22.25.30](https://canada1.discourse-cdn.com/flex011/uploads/kirupa/original/3X/2/8/28c9b74e1da1e3ebc3427037be1f9608252555e6.png)

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

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