Building a To-Do List App Using React - TechvBlogs

Building a To-Do List App Using React

Learn how to build a To-Do List app using React with this step-by-step guide. Covering key concepts including components, state, props, and event handling, this tutorial is suitable for beginners looking to build simple user interfaces with React.


Suresh Ramani - Author - TechvBlogs
Suresh Ramani
 

1 year ago

TechvBlogs - Google News

React.js is a popular JavaScript library used for building user interfaces. It was developed by Facebook and has quickly become one of the most popular libraries in the JavaScript community. React.js makes it easy to create reusable components and manage state, making it a great choice for building web applications.

In this article, we'll walk through the process of building a To-Do List app using React.js. We'll cover the basics of setting up a React project, creating components, managing state, and handling user interactions. By the end of this article, you'll have a good understanding of how to build a simple web application using React.js.

Building a To-Do List App Using React

Now, let's proceed with the first step.

Step 1: Setting up the environment

The first step to building a To-Do List app using React is to set up the development environment. We can do this by creating a new React project using Create React App.

To get started, open your terminal and type the following command:

npx create-react-app todo-list-app

This will create a new React project named todo-list-app. Once the project is created, navigate to the project directory using the following command:

cd todo-list-app

Step 2: Creating the To-Do List component

Now that we have our project set up, let's create our first React component, the To-Do List component.

In the src folder of our project, create a new file named TodoList.js. In this file, we will create a functional component that will render our To-Do List.

Here's the code to create the component:

import React from 'react';

function TodoList() {
  return (
    <div>
      <h1>To-Do List</h1>
      {/* Add your To-Do List code here */}
    </div>
  );
}

export default TodoList;

This code imports React and creates a functional component named TodoList. The TodoList component returns a div with an h1 element that displays the title of our To-Do List.

Now that we have created our To-Do List component, let's move on to the next step.

Step 3: Creating the Add Task component

In order to add tasks to our To-Do List, we need to create an Add Task component. This component will be responsible for taking user input and adding it to our To-Do List.

In the src folder, create a new file named AddTask.js. In this file, we will create a class component that will render a form for the user to add a new task.

Here's the code to create the component:

import React, { Component } from 'react';

class AddTask extends Component {
  state = {
    task: ''
  };

  handleInputChange = e => {
    this.setState({ task: e.target.value });
  };

  handleSubmit = e => {
    e.preventDefault();
    this.props.onAddTask(this.state.task);
    this.setState({ task: '' });
  };

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input
          type="text"
          placeholder="Add Task"
          value={this.state.task}
          onChange={this.handleInputChange}
        />
        <button>Add</button>
      </form>
    );
  }
}

export default AddTask;

This code imports React and creates a class component named AddTask. The AddTask component contains a state object with a task property that represents the input value of the form. We also have two methods, handleInputChange and handleSubmit. handleInputChange updates the task property of the state object with the current value of the input field, while handleSubmit prevents the default form submission behavior and calls the onAddTask method with the current value of the input field. Finally, the render method returns a form with an input field and a button.

Now that we have created our Add Task component, let's move on to the next step.

Step 4: Creating the Task component

To display the tasks in our To-Do List, we need to create a Task component. This component will render each individual task in our list.

In the src folder, create a new file named Task.js. In this file, we will create a functional component that will render a single task.

Here's the code to create the component:

import React from 'react';

function Task(props) {
  return (
    <li>
      {props.task}
      <button onClick={() => props.onDeleteTask(props.id)}>Delete</button>
    </li>
  );
}

export default Task;

This code imports React and creates a functional component named Task. The Task component takes in two props, task and onDeleteTask. task is the task text that we want to display, and onDeleteTask is a function that will be called when the delete button is clicked. The render method returns a list item that displays the task text and a delete button. When the delete button is clicked, it calls the onDeleteTask function with the task's id as an argument.

Step 5: Adding state to the To-Do List component

Now that we have created our individual components, we can start building out our To-Do List component. First, we need to add some state to the component to keep track of the tasks.

In the TodoList.js file, add the following code:

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

class TodoList extends Component {
  state = {
    tasks: [
      { id: 1, task: 'Buy groceries' },
      { id: 2, task: 'Go for a walk' }
    ]
  };

  renderTasks() {
    return this.state.tasks.map(task => (
      <Task key={task.id} id={task.id} task={task.task} onDeleteTask={this.handleDeleteTask} />
    ));
  }

  handleAddTask = task => {
    const tasks = [...this.state.tasks];
    tasks.push({ id: tasks.length + 1, task });
    this.setState({ tasks });
  };

  handleDeleteTask = id => {
    const tasks = [...this.state.tasks];
    const index = tasks.findIndex(task => task.id === id);
    tasks.splice(index, 1);
    this.setState({ tasks });
  };

  render() {
    return (
      <div>
        <h1>To-Do List</h1>
        <AddTask onAddTask={this.handleAddTask} />
        <ul>{this.renderTasks()}</ul>
      </div>
    );
  }
}

export default TodoList;

This code imports React, as well as our Task and AddTask components. We create a class component named TodoList and add some initial state with two tasks. We also add two methods, handleAddTask and handleDeleteTask, which will be called when a task is added or deleted. handleAddTask creates a new task object and adds it to the tasks array in the state. handleDeleteTask removes the task with the specified id from the tasks array in the state.

We also add a renderTasks method, which maps over the tasks array in the state and renders a Task component for each task. We pass in the id, task, and onDeleteTask props to each Task component.

Finally, the render method returns our To-Do List component with the AddTask and Task components.

Now that we have added state to our To-Do List component, let's move on to the next step.

Step 6: Adding new tasks to the To-Do List

Now that we have added state to our To-Do List component, let's add the ability to add new tasks.

In the AddTask.js file, add the following code:

import React, { Component } from 'react';

class AddTask extends Component {
  state = {
    task: ''
  };

  handleChange = e => {
    this.setState({ task: e.target.value });
  };

  handleSubmit = e => {
    e.preventDefault();
    this.props.onAddTask(this.state.task);
    this.setState({ task: '' });
  };

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input type="text" value={this.state.task} onChange={this.handleChange} />
        <button>Add Task</button>
      </form>
    );
  }
}

export default AddTask;

This code imports React and creates a class component named AddTask. We add some initial state with an empty task string. We also add two methods, handleChange and handleSubmit, which will be called when the input field is changed or when the form is submitted.

handleChange updates the state with the new task text. handleSubmit prevents the default form submission behavior, calls the onAddTask prop with the new task text as an argument, and then clears the input field by resetting the task state.

Finally, the render method returns a form with an input field and a submit button. The input field's value is bound to the task state, and the handleChange method is called whenever the input field is changed.

In the TodoList.js file, we have already added the AddTask component to the render method of the TodoList component, and we have added a handleAddTask method that is called when a new task is added.

Step 7: Marking tasks as completed

Now, let's add the ability to mark tasks as completed. We'll add a checkbox to each task and update the state of the task when the checkbox is clicked.

In the TodoList.js file, update the Task component as follows:

class Task extends Component {
  handleToggleCompleted = () => {
    this.props.onToggleCompleted(this.props.task.id);
  };

  render() {
    const { task } = this.props;

    return (
      <div>
        <input
          type="checkbox"
          checked={task.completed}
          onChange={this.handleToggleCompleted}
        />
        {task.text}
      </div>
    );
  }
}

We add a new method called handleToggleCompleted that is called when the checkbox is clicked. This method calls the onToggleCompleted prop with the id of the task as an argument.

In the TodoList component, add the following method:

handleToggleCompleted = id => {
  const { tasks } = this.state;
  const index = tasks.findIndex(task => task.id === id);
  const updatedTasks = [
    ...tasks.slice(0, index),
    { ...tasks[index], completed: !tasks[index].completed },
    ...tasks.slice(index + 1)
  ];

  this.setState({ tasks: updatedTasks });
};

This method takes the id of the task that was clicked and uses it to find the index of the task in the tasks array. We then create a new array of tasks with the task at the given index updated to toggle the completed state.

Finally, we set the state of the tasks array to the updated array.

With this update, when a user clicks on a checkbox, the corresponding task will be marked as completed, and the checkbox will be checked.

Step 8: Filtering tasks

Let's add a filter to our To-Do List, so the user can toggle between seeing all tasks, completed tasks, or incomplete tasks.

In the TodoList.js file, add the following state to the TodoList component:

state = {
  tasks: [],
  filter: 'all'
};

We add a new filter state that starts with the value 'all'.

Next, add the following methods to the TodoList component:

handleFilterChange = filter => {
  this.setState({ filter });
};

getFilteredTasks = () => {
  const { tasks, filter } = this.state;

  switch (filter) {
    case 'completed':
      return tasks.filter(task => task.completed);
    case 'incomplete':
      return tasks.filter(task => !task.completed);
    default:
      return tasks;
  }
};

handleFilterChange is called when the user clicks on a filter button. It takes the filter as an argument and updates the filter state accordingly.

getFilteredTasks returns the tasks that match the current filter.

In the render method of the TodoList component, update the code to include filter buttons and to display only the filtered tasks:

render() {
  const { tasks, filter } = this.state;
  const filteredTasks = this.getFilteredTasks();

  return (
    <div>
      <h1>To-Do List</h1>
      <AddTask onAddTask={this.handleAddTask} />
      <div>
        <button onClick={() => this.handleFilterChange('all')} disabled={filter === 'all'}>
          All
        </button>
        <button onClick={() => this.handleFilterChange('completed')} disabled={filter === 'completed'}>
          Completed
        </button>
        <button onClick={() => this.handleFilterChange('incomplete')} disabled={filter === 'incomplete'}>
          Incomplete
        </button>
      </div>
      {filteredTasks.map(task => (
        <Task key={task.id} task={task} onToggleCompleted={this.handleToggleCompleted} />
      ))}
    </div>
  );
}

We create three filter buttons that call the handleFilterChange method when clicked. We also disable the button that matches the current filter.

Finally, we update the filteredTasks variable to contain only the tasks that match the current filter.

With these changes, the user can now toggle between seeing all tasks, completed tasks, or incomplete tasks.

To run the code, open your terminal and navigate to the root folder of your project. Then, run the following command:

npm start

This will start the development server and open the app in your default web browser. You should now be able to interact with the To-Do List app you just built!

Conclusion

In conclusion, building a To-Do List app using React can be a great way to learn the basics of React and practice building user interfaces. We started by setting up our project using create-react-app, and then created several components including TodoList, AddTask, and Task. We also used React's state to keep track of our tasks and to allow users to toggle the completion status of each task. Finally, we added a filter to our To-Do List, so the user can toggle between seeing all tasks, completed tasks, or incomplete tasks.

Throughout this tutorial, we've covered several important concepts in React including components, state, props, and event handling. While this app is relatively simple, it provides a great foundation for building more complex apps in the future.

I hope you found this tutorial helpful and that you're excited to continue learning and building with React!

Comments (0)

Comment


Note: All Input Fields are required.