React

React To-Do List Tutorial

Learn how to create a functional To-Do list application using React's core concepts like components, state management, and event handling.


1. Set Up Your React App

First, create a new React application using create-react-app or your preferred build tool. We'll use functional components with React hooks.


npx create-react-app todo-tutorial
cd todo-tutorial
npm start


2. Component Structure

This To-Do list will have three components:

  • App: Main container component to manage state
  • TodoForm: Input form to add new tasks
  • TodoList: Renders list items

3. Implement the To-Do Form

Use the useState hook to manage the input state and form submission.


// TodoForm.js
import { useState } from 'react';

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

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

  return (
    <form className="flex gap-2" onSubmit={handleSubmit}>
      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Add new task"
        className="flex-1 px-4 py-2 rounded-l-lg border border-gray-300"
      />
      <button
        type="submit"
        className="bg-cyan-600 text-white px-4 py-2 rounded-r-lg hover:bg-cyan-700 transition-colors"
      >
        Add
      </button>
    </form>
  );
}


4. Display and Manage To-Do Items

Here's the complete To-Do list implementation with state management:


// App.js
import { useState } from 'react';
import TodoForm from './TodoForm';
import TodoList from './TodoList';

function App() {
  const [todos, setTodos] = useState([
    { id: 1, text: 'Complete tutorial', completed: false },
    { id: 2, text: 'Write JavaScript', completed: true },
    { id: 3, text: 'Create React app', completed: false },
  ]);

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

  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));
  };

  return (
    <div className="max-w-md mx-auto">
      <h1 className="text-2xl font-bold mb-4 text-cyan-600">My To-Do List</h1>
      <TodoForm addTodo={addTodo} />
      <TodoList todos={todos} toggleTodo={toggleTodo} deleteTodo={deleteTodo} />
    </div>
  );
}

export default App;

5. Create To-Do Item Component


// TodoList.js
export default function TodoList({ todos, toggleTodo, deleteTodo }) {
  return (
    <ul className="space-y-3 mt-4">
      {todos.map((todo) => (
        <li key={todo.id} className="bg-gray-50 p-3 rounded-lg flex justify-between items-center">
          <div className="flex items-center">
            <input
              type="checkbox"
              checked={todo.completed}
              onChange={() => toggleTodo(todo.id)}
              className="mr-2"
            />
            <span className={todo.completed ? 'line-through text-gray-500' : ''}>
              {todo.text}
            </span>
          </div>
          <button
            onClick={() => deleteTodo(todo.id)}
            className="text-red-500 hover:text-red-700 transition-colors"
          >
            &times;
          </button>
        </li>
      ))}
    </ul>
  );
}


6. Try the Example

Click the button below to see a working To-Do list example with complete state handling and interactivity:

View Example

Interactive To-Do Example


7. Key Concepts Demonstrated

  • useState – For managing input and todo state
  • Event Handling – Handling form submissions and checkbox changes
  • Conditional Rendering – Strikethrough completed items
  • Component Separation – Form and List as separate components
  • JSX – Declarative UI updates