Todo App

Introduction

After completing my first logic-focused project (Counters), I wanted to take the next natural step in complexity — not by improving the UI, but by challenging my thinking.

This led me to Project 2: Todo App (Logic-First, Not UI).

Why a Todo App?

Counters helped me understand single-value state logic.
A Todo app forces you to think in terms of:

  • Arrays instead of single values
  • CRUD operations (add, update, delete)
  • Conditional rendering
  • Edge cases and state consistency

This is where many React learners start to struggle — which makes it the perfect place to grow.

The goal of this project was not to build a fancy interface, but to strengthen my problem-solving approach, write predictable state updates, and handle real-world logic scenarios that appear in almost every frontend application.

In this article, I’ll break down how I approached the Todo app step by step, the logic decisions I made, the mistakes I encountered, and what I learned by solving them.

Level-by-Level Development 🚀

Level 1: Add Todo Creation with Validation

Commit: Level 1: Add todo creation with validation

const [todos, setTodos] = useState([]);
const [task, setTask] = useState(“”);

const handleSubmit = () => {
if (task.trim() === “”) {
alert(“Enter task to add”);
return;
}

setTodos([…todos, task]);
setTask(“”);
};

type=”text”
placeholder=”Add task…”
value={task}
onChange={(e) => setTask(e.target.value)}
className=”border rounded px-2 py-2 w-80 m-2″
/>

onClick={handleSubmit}
className=”border rounded p-2 w-25 cursor-pointer hover:bg-gray-400 hover:text-black”

Add Task

{todos.map((todo, idx) => (

))}

Learnings

  1. Controlled Inputs
    Learned how to manage form inputs using useState, keeping the input value fully controlled by React state.

  2. Basic Validation
    Added validation to prevent empty or whitespace-only todos from being added:

if (task.trim() === “”) {
alert(“Enter task to add”);
return;
}

This helps maintain clean and meaningful data.

  1. Immutable State Updates (Arrays)
    Used the spread operator to update the todos array:

setTodos([…todos, task]);

  • …todos copies all existing tasks
  • task adds the new task at the end
  • A new array is created instead of modifying the old one
  • This follows React’s immutability rule and ensures proper re-rendering.
  1. Resetting Input for Better UX
    Cleared the input field after adding a todo:

setTask(“”);

  1. Rendering Dynamic Lists
    Used map() to render todos dynamically:

{todos.map((todo, idx) => (

))}

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post

How You.com 10x’d MQLs with multithreaded marketing

Next Post

Revolutionize Testing with Tricentis: Unleash the Power of AI and Automation

Related Posts