DEV Community

Dev Khatri
Dev Khatri

Posted on

create todo app in react

Motivation

Learn some concepts of react while creating a todo list app

Let's start

A basic todo list would have following things for sure,

  • add todo
  • show todo
  • delete todo

visualization is more important, they say..

so let’s create something like this…

Add TODO

To add an item we would need a simple textbox

<input type="text"/>
Enter fullscreen mode Exit fullscreen mode

let's put some state in place

this.state = { new_text: "" }
Enter fullscreen mode Exit fullscreen mode

now text box takes the value from our state

<input type="text" value={this.state.new_text} />
Enter fullscreen mode Exit fullscreen mode

now if we type anything in the textbox, we may not see any values getting typed in the textbox,
because textbox is getting the value from the state and that is empty and not getting updated yet.

How do we update our state now ?

<input type="text" onChange={handleChange} value={todo.text} />
Enter fullscreen mode Exit fullscreen mode

function,

handleChange(e) {
    this.setState({ new_text: e.target.value })
}
Enter fullscreen mode Exit fullscreen mode

now we have our todo in sync with component state,

but our state is handling one item at a time. we may have to update our state definition that stores multiple items,

this.state = {
    items: [],
    new_text: ""
}
Enter fullscreen mode Exit fullscreen mode

let’s use form submit to set todo

<form onSubmit={this.handleSubmit}>
  <input type="text" onChange={this.handleChange} value={this.state.new_text} />
    <button>Add</button>
</form>
Enter fullscreen mode Exit fullscreen mode

function,

handleSubmit(e){
    e.preventDefault();
    let newItem = {
        new_text : this.state.new_text
    }
    this.setState(state=>({
        items : state.items.concat(newItem),
        new_text:''
      }))
  }
Enter fullscreen mode Exit fullscreen mode

Note: when any form submit is performed, page re-renders hence preventing it,

          event.preventDefault();
Enter fullscreen mode Exit fullscreen mode

our next task is to show the todos in the list below the textbox.

Show todo

Add a list to show all the todos, to display the list items we add one more component [Todolist] and add a list in it

<ul>
  {this.props.items.map(item=>(
      <li>{item.new_text}
      </li>
  ))}
</ul>
Enter fullscreen mode Exit fullscreen mode

and display just below the textbox,

 <Todolist items = {this.state.items} />
Enter fullscreen mode Exit fullscreen mode

Now we have our app that lets us type text in text box , and shows the list under it, but what is this error in the console !!

this is caused when you are displaying items and has no unique identifier, hence we may have to add some unique identifier for the list item.

"Dates are important"

Let’s put the id wherever we are using our list items

 handleSubmit(e){
        e.preventDefault();
        let newItem = {
            new_text : this.state.new_text,
            id: Date.now()
        }
        this.setState(state=>({
            items : state.items.concat(newItem),
            new_text:''
        }))
    }
Enter fullscreen mode Exit fullscreen mode

and while showing the list items,

<ul>
  {this.props.items.map(item=>(
      <li key={item.id}>{item.new_text}
      </li>
  ))}
</ul>
Enter fullscreen mode Exit fullscreen mode

now we have our app running without any error.

This is the flow for our app,

Wait, we discussed delete as well right…

How do we accommodate delete functionality here, when one component triggers action and another component must be updated. Currently, child component does not have capability to update the state.

To achieve this, we will use react hooks.

There are many ways we can add hooks, I like the following,

we create a separate file that performs all the crud information on the state and uses the state internally

export const TodoRepo = (initialValue = []) => {
    const [todos, setTodos] = useState([]);
    return {
        todos,
        addTodo: item => {
            if (item.new_text != "") {
                setTodos(
                    todos.concat(item)
                )
            }
        },
        deleteTodo: item => {
            if (item.new_text != "") {
                setTodos(
                    todos.filter((td) => {
                        return td.id != item.id
                    })
                )
            }
        }
    }
};
Enter fullscreen mode Exit fullscreen mode

and we use this js file in our first component [ Todo_App]

<ul>
    {todos.map(item => (
      <li key={item.id}>{item.new_text}<button onClick={()=>{deleteTodo(item)}}> delete</button></li>
    ))}
</ul>
Enter fullscreen mode Exit fullscreen mode

Now we have the hooks configured in our app that adds/shows/deletes list items.I have setup the todo list with material-ui and have deployed here,
https://github.com/khatridev/react-todolist

I will keep adding more features in it, would be happy to hear any feedbacks.

Top comments (0)