Loading

Quipoin Menu

Learn • Practice • Grow

react / Todo App Project
tutorial

Todo App Project

Every React beginner builds a Todo app – and for good reason. It's the perfect project to understand the core concepts of React: components, state, props, events, and forms. In this chapter, we'll build a complete Todo application step by step.

What We're Building

A classic Todo app where users can:
  • Add new todos.
  • Mark todos as completed.
  • Delete todos.
  • Filter todos (All / Active / Completed).

A Todo app is like the "Hello World" of React – it touches every fundamental concept and gives you a solid foundation.

Step 1: Setting Up the Project
npx create-react-app todo-app
cd todo-app
npm start

Step 2: Planning Components

We'll create these components:
  • App – main container, holds state and logic.
  • TodoForm – input field to add new todos.
  • TodoList – renders the list of todos.
  • TodoItem – individual todo with checkbox and delete button.
  • FilterButtons – buttons to change filter.

Step 3: Building the App Component
import React, { useState } from 'react';
import TodoForm from './TodoForm';
import TodoList from './TodoList';
import FilterButtons from './FilterButtons';

function App() {
  const [todos, setTodos] = useState([]);
  const [filter, setFilter] = useState('all');

  const addTodo = (text) => {
    const newTodo = { id: Date.now(), text, completed: false };
    setTodos([...todos, newTodo]);
  };

  const toggleTodo = (id) => {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ));
  };

  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };

  const getFilteredTodos = () => {
    switch (filter) {
      case 'active': return todos.filter(todo => !todo.completed);
      case 'completed': return todos.filter(todo => todo.completed);
      default: return todos;
    }
  };

  return (
    <div>
      <h1>Todo App</h1>
      <TodoForm addTodo={addTodo} />
      <FilterButtons filter={filter} setFilter={setFilter} />
      <TodoList
        todos={getFilteredTodos()}
        toggleTodo={toggleTodo}
        deleteTodo={deleteTodo}
      />
    </div>
  );
}

export default App;

Step 4: TodoForm Component
import React, { useState } from 'react';

function TodoForm({ addTodo }) {
  const [text, setText] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    if (text.trim()) {
      addTodo(text);
      setText('');
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Add a new todo..."
      />
      <button type="submit">Add</button>
    </form>
  );
}

export default TodoForm;

Step 5: TodoItem and TodoList Components
<!-- TodoItem.js -->
function TodoItem({ todo, toggleTodo, deleteTodo }) {
  return (
    <li>
      <input
        type="checkbox"
        checked={todo.completed}
        onChange={() => toggleTodo(todo.id)}
      />
      <span style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>
        {todo.text}
      </span>
      <button onClick={() => deleteTodo(todo.id)}>Delete</button>
    </li>
  );
}

<!-- TodoList.js -->
function TodoList({ todos, toggleTodo, deleteTodo }) {
  return (
    <ul>
      {todos.map(todo => (
        <TodoItem
          key={todo.id}
          todo={todo}
          toggleTodo={toggleTodo}
          deleteTodo={deleteTodo}
        />
      ))}
    </ul>
  );
}

Step 6: FilterButtons Component
function FilterButtons({ filter, setFilter }) {
  const filters = ['all', 'active', 'completed'];
  return (
    <div>
      {filters.map(f => (
        <button
          key={f}
          onClick={() => setFilter(f)}
          style={{ fontWeight: filter === f ? 'bold' : 'normal' }}
        >
          {f.charAt(0).toUpperCase() + f.slice(1)}
        </button>
      ))}
    </div>
  );
}

Two Minute Drill

  • A Todo app teaches React fundamentals: components, state, props, events, and forms.
  • Use `useState` to manage todos and filter.
  • Break UI into small, reusable components.
  • Pass data down via props, and pass functions up to modify state.
  • Filtering is done by computing a derived list based on filter state.

Need more clarification?

Drop us an email at career@quipoinfotech.com