Learn how to create react todo list app with examples.

Introduction react todo list

In this tutorial I am going to cover how to create react todo list app with few very easy steps.  In other words react js hello world app. Everything you may need will cover from A to Z with react js examples . Here I am using ES6 syntax which make your code easy to read and write.

If you have no idea about creating react web application, today I am going to cover basic this you may need to create simple react web application, that you can scale up to complex react application without any burden.  Learn how to create react application in development mode and once finish deploy your application in production environment.

 

Reactjs todo application example 

This is an very simple react todo app demo created using bootstrap.
Enable Javascript to run this example
Download Source Code download react js todo list

Step 1: Setup react starter kit

Before we begin we have to setup react starter kit. download react starter kit from below link. After downloading the starter kit continue reading this articke if you don't know how to run the starter kit.

Download Now

Download via GitHub

Refer this article to create your own react starter kit Learn how to create your own react starter kit

Using the terminal go to download folder where you can see package.json file (contains required packages). From there enter below commands to run the application.

npm i
npm start

Then using browser go to http://localhost:3000 . Congratulations you just setup development environment for our react application. 

Step 2: Creating basic component structure of our application

Below picture shows basic react component structure that can be used to create our react todo application

react component structure for react todo application

Step 3: Designing basic HTML and CSS for our react application.

Once you download and run above react starter kit you will see some text like “My React Application” in your browser.  Using bootstrap I created a simple todo layout. Copy and replace  MainContainer class with with below give class.

class MainContainer extends React.Component{
	render(){
		return(
    <div>
        <div className = "row">
            <div className="col-md-12">
                <div style = {{textAlign:"center"}}>
                    <h2> Bootstrap React TODO Application </h2>
                </div>
            </div>
        </div>
        <div className = "row">
            <div className = "col-md-6 col-md-offset-3">
                <div style = {{margin:"20px"}}>
                    <div className="row">
                            <div className="col-md-7">
                                <input type="text" className="form-control" placeholder="your task"/>
                            </div>
                            <div className="col-md-4">
                                <button className="btn btn-primary"> Create New Task </button>
                            </div>
                    </div>
                </div>
            </div>
        </div>
            <div className="row">
                <div className = "col-md-8 col-md-offset-2">
                    <div className="panel panel-default">
                        <div className="panel-body">
                        <div className="list-group">
                            <a href="#" className="list-group-item">Dapibus ac facilisis in <i style = {{float:"right"}} className="glyphicon glyphicon-remove"> </i></a>
                            <a href="#" className="list-group-item">Morbi leo risus <i style = {{float:"right"}} className="glyphicon glyphicon-remove"> </i></a>
                            <a href="#" className="list-group-item">Porta ac consectetur ac <i style = {{float:"right"}} className="glyphicon glyphicon-remove"> </i></a>
                            <a href="#" className="list-group-item">Vestibulum at eros <i style = {{float:"right"}} className="glyphicon glyphicon-remove"> </i></a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
			)
	}
}

Open your browser and you will see something similar to below picture

react component structure of todo application

This is how above interface is broken down into react components as show in step 2

structuring interface into components

Step 4: Separating into react components.

create following files in following locations

# src/components/createTaskForm.js
# src/components/task.js
# src/containers/listTaskContainer.js

Using the diagram shown in step 3, you will now understand what component goes inside each file. So let’s add html to those files.  Since we are using ES6 syntax it will easier for you to read each line of code.

Below shows how above HTML is separated into files. Please note that each created components are linked to entry.js either directly or indirectly (via another file). After copy and pasting below codes you will see static output (CSS only structure) in your browser without any functionality.

Note: Every time when you use react component first letter of the react component should be in capital,
Ex: import Task from “../components/task.js”.
If not it will be treated as a basic html component.

# src/components/createTaskForm.js

import React, {Component} from "react"

export default class CreateTaskForm extends Component{

  constructor(props){
    super(props)
  }

  render(){
    return(
      <div className = "row">
        <div className = "col-md-6 col-md-offset-3">
            <div style = {{margin:"20px"}}>
                <div className="row">
                    <div className="col-md-7">
                        <input type="text" className="form-control" placeholder="your task"/>
                    </div>
                    <div className="col-md-4">
                        <button className="btn btn-primary"> Create New Task </button>
                    </div>
                </div>
            </div>
        </div>
    </div>
    )
  }
}

# src/components/task.js

import React, {Component} from "react"

export default class Task extends Component{
  constructor(props) {
    super(props)
  }

  render(){
    return(
        <a href="#" className="list-group-item">Dapibus ac facilisis in
            <i style = {{float:"right"}} className="glyphicon glyphicon-remove"></i>
        </a>
    )
  }
}

# src/containers/listTaskContainer.js


import React, {Component} from "react"

//Components
import Task from "../components/task.js"

export default class ListTaskContainer extends Component{

  constructor(props) {
    super(props)
  }

  render(){
    return(
      <div className="row">
        <div className = "col-md-8 col-md-offset-2">
            <div className="panel panel-default">
              <div className="panel-body">
              <div className="list-group">
                <Task/>
                </div>
              </div>
          </div>
        </div>
      </div>
    )
  }
}

# entry.js

import React from "react"
import {render} from "react-dom"

//Components
import ListTaskContainer from "./containers/listTaskContainer.js"
import CreateTaskForm from "./components/createTaskForm.js"

class MainContainer extends React.Component{

	constructor(props){
		super(props)
	}

	render(){
		return(
                    <div>
                        <div className = "row">
                            <div className="col-md-12">
                                <div style = {{textAlign:"center"}}>
                                    <h2> Bootstrap React TODO Application </h2>
                                </div>
                            </div>
                        </div>
                        {/*Create Task Form */}
                        <CreateTaskForm/>
                        {/* Show Task list */}
                        <ListTaskContainer/>
                    </div>

			)
	}
}


render(
	<MainContainer/>
	,
	document.getElementById("root")
	)

Step 5: Listing created tasks.

What is done here is;
When we provide an array of tasks to taskListContainer it will show list of tasks and when we click on close button that task will be removed

Note:
Data pass from component to component is by using props. Data managed inside a component is using states. Props or data received using props are immutable (constants or cannot change). states are mutable.

# src/components/task.js

import React, {Component} from "react"

export default class Task extends Component{
  constructor(props) {
    super(props)
    this.handleCloseTask = this.handleCloseTask.bind(this)
  }

  static propTypes = {
    id: React.PropTypes.number.isRequired, //Define that id of type int is needed when you use this component
    name: React.PropTypes.string.isRequired, //Define that name of type string is needed when you use this component
    onClose: React.PropTypes.func.isRequired,//Define that onClose function is needed when you use this component
  }

  render(){
    return(
      <a href="#" className="list-group-item">
        {this.props.name}
        <button onClick = {this.handleCloseTask} style = {{float:"right"}}>
          <i className="glyphicon glyphicon-remove"> </i>
        </button>
      </a>
    )
  }

  handleCloseTask(){
    this.props.onClose(this.props.id)
  }
}

Here task component is changed to accept name prop in order to display task. prop id is
used to track each task seperately. onClose function is used to tell that user click on
task close button. We are sending task id on task close.

# src/containers/listTaskContainer.js

import React, {Component} from "react"
//Components
import Task from "../components/task.js"

export default class ListTaskContainer extends Component{
  constructor(props) {
    super(props)
    this.handleCloseTask = this.handleCloseTask.bind(this)
  }
  static propTypes = {
      list:React.PropTypes.array.isRequired, //Define that list of array is needed when you use this component
      removeTask: React.PropTypes.func.isRequired
  }

  render(){
    return(
      <div className="row">
        <div className = "col-md-8 col-md-offset-2">
            <div className="panel panel-default">
              <div className="panel-body">
              <div className="list-group">
                {
                  this.props.list.map((value, index) => (
                      <Task
                        key = {index}
                        id = {index}
                        name = {value}
                        onClose = {this.handleCloseTask}
                      />
                  ))
                }
                </div>
              </div>
          </div>
        </div>
      </div>
    )
  }

  handleCloseTask(id){
    this.props.removeTask(id)
  }
}

Here we are accepting a prop "list". It is an array that is used to display tasks.
removeTask() function is called immediately after onClose() function, which is called from
task component.

# entry.js

import React from "react"
import {render} from "react-dom"

//Components
import ListTaskContainer from "./containers/listTaskContainer.js"
import CreateTaskForm from "./components/createTaskForm.js"

class MainContainer extends React.Component{

	constructor(props){
		super(props)
		this.state = {
			taskList:[]
			}
			this.handleRemoveTask = this.handleRemoveTask.bind(this)
	}

	componentDidMount(){
		this.setState({
			taskList:["Task 1", "Task 2", "Task 3"]
		})
	}

	render(){
		return(
                    <div>
                        <div className = "row">
                            <div className="col-md-12">
                                <div style = {{textAlign:"center"}}>
                                    <h2> Bootstrap React TODO Application </h2>
                                </div>
                            </div>
                        </div>
                        {/*Create Task Form */}
                        <CreateTaskForm/>

                        {/* Show Task list */}
                        <ListTaskContainer
                            list = {this.state.taskList}
                            removeTask = {this.handleRemoveTask}
                        />
                    </div>

			)
	}

	handleRemoveTask(id){
            let array = this.state.taskList;

            /* Remove selected value from array */
            array = array.filter(function (el, index) {
                     return index !== id
            });

            this.setState({taskList: array});
	}
}


render(
	<MainContainer/>
	,
	document.getElementById("root")
	)


Here we just passed an custom created array to listTaskContainer and add new function to filter array based on it’s id (handleRemoveTask()) . When you go through the code you will see that taskList is the array that is going to be change and it is assign to component state. When final created array is added to state, it is passed to listTaskContainer component as a prop.

componentDidMount() function is react based function which is triggered after component is mounted.
Here is the list of some important react life cycle functions.

componentWillMount(){
//Triggered before component get mounted
}
componentDidMount(){
//Triggred after component get mounted
}
componentWillUnmount(){
//triggered when component unmount
}
componentWillReceiveProps(nextProps){
//triggred when component receive props after mounting.
}

Step 6: Create tasks and viewing them

# src/components/createTaskForm.js

import React, {Component} from "react"
export default class CreateTaskForm extends Component{

  constructor(props){
    super(props)
    this.state = {
      taskName:""
    }
    this.handleAddTask = this.handleAddTask.bind(this)
  }

  static proptypes = {
    newTask: React.PropTypes.func.isRequired
  }

  render(){
    return(
        <div className = "row">
            <div className = "col-md-6 col-md-offset-3">
                <div style = {{margin:"20px"}}>
                    <div className="row">
                        <div className="col-md-7">
                            <input
                                type="text"
                                className="form-control"
                                placeholder="your task"
                                onChange = {e => this.updateTaskName(e)}
                                value = {this.state.taskName}
                                onKeyPress = {e => this.checkEnterKey(e)}
                              />
                        </div>
                        <div className="col-md-4">
                            <button type = "button" className="btn btn-primary" onClick = {this.handleAddTask}> Create New Task </button>
                        </div>
                    </div>
                </div>
            </div>
    </div>
    )
  }

  checkEnterKey(e){
    var keyCode = e.which || e.keyCode;
    if(keyCode == 13){
      if(this.state.taskName.trim() !== ""){
          this.props.newTask(this.state.taskName)
      }
    }
  }

  updateTaskName(e){
    this.setState({taskName: e.target.value})
  }

  handleAddTask(e){
    let name = e.target.value
    if(this.state.taskName.trim() !== "")
      this.props.newTask(this.state.taskName)
  }

}

Here we are triggering function newTask() through props when we press enter key or press the create button.
With that function we are sending name of the task that user entered. That's all.  For those who are new to react, the other functions like updateTaskName() function will update component state with user entered data as user start to type. checkEnterKey() function is used to detect user pressed the enter key in input field.

# entry.js


\***
   ............
***\
        constructor(props){
            super(props)

            this.state = {
                taskList:[]
                }

            this.handleRemoveTask = this.handleRemoveTask.bind(this)
            this.handleAddTask = this.handleAddTask.bind(this)
	}
\***
   ............
***\
        render(){
            return(
                <div>
                    <div className = "row">
                        <div className="col-md-12">
                            <div style = {{textAlign:"center"}}>
                                            <h2> Bootstrap React TODO Application </h2>
                            </div>
                        </div>
                    </div>

                    {/*Create Task Form */}
                    <CreateTaskForm
                            newTask = {this.handleAddTask}
                    />

                    {/* Show Task list */}
                    <ListTaskContainer
                            list = {this.state.taskList}
                            removeTask = {this.handleRemoveTask}
                    />
            </div>

            )
	}
\***
   ............
***\
	handleAddTask(name){
		let tmp = this.state.taskList;
		tmp.push(name);
		this.setState({taskList: tmp})
	}

\***
   ............
***\

When user add new task the newTask() function on createTaskForm component is triggered and
that is handle by handleAddTask() function. In that function we push newly created task into task array and re render the component in order to show newly added task. Re render occure when component's state changed.

Download react todo web application

Download Now

Help: Using the terminal go to download folder where you can see package.json file. From there  enter below commands to run the application and then using browser go to http://localhost:3000 to see working react todo application.

npm i
npm start