Introduction
A Todo App is one of the most popular beginner projects in ReactJS. It helps developers understand core React concepts while building a real-world application.
A Todo application allows users to:
- Add tasks
- Delete tasks
- Mark tasks as completed
- Manage daily activities
Most React beginners start their journey with a Todo application because it combines many important React concepts into a single project.
In this tutorial, you will learn how to create a complete Todo App in React step by step.
What is a Todo App?
A Todo App is a task management application where users can:
- Create tasks
- View tasks
- Update tasks
- Delete tasks
This is also called a CRUD application.
Features of Todo App
Our React Todo App will include:
- Add new task
- Display task list
- Delete task
- Mark task completed
- Dynamic UI updates
Technologies Used
We will use:
- ReactJS
- JSX
- useState Hook
- CSS
Setting Up React Project
Create a React app using Vite.
Create Project
npm create vite@latest
Install Dependencies
npm install
Run Development Server
npm run dev
Project Structure
src/
├── App.jsx
├── App.css
Understanding Todo App Flow
Step 1
User enters task.
Step 2
Task stores in state.
Step 3
React updates UI automatically.
Step 4
User can delete or complete tasks.
Creating Basic Todo App
App.jsx
import { useState } from "react";
function App() {
const [task, setTask] = useState("");
const [tasks, setTasks] = useState([]);
const addTask = () => {
if (task === "") return;
setTasks([
...tasks,
task
]);
setTask("");
};
return (
<div>
<h1>Todo App</h1>
<input
type="text"
placeholder="Enter task"
value={task}
onChange={(e) =>
setTask(e.target.value)
}
/>
<button onClick={addTask}>
Add
</button>
{tasks.map((item, index) => (
<h3 key={index}>
{item}
</h3>
))}
</div>
);
}
export default App;
Understanding useState in Todo App
We use two states:
1. Stores input field value.
const [task, setTask] = useState("");
2. Stores all tasks
const [tasks, setTasks] = useState([]);
How Add Task Works?
Step 1
User types a task in the input.
Step 2
onChange updates state.
Step 3
Button click triggers addTask().
Step 4
Task adds into array.
Step 5
React re-renders updated UI.
Dynamic Rendering Using map()
React uses map() to display all tasks.
Example
tasks.map((item, index) => (
<h3>
{item}
</h3>
))
Why key Prop is Important?
React needs unique keys for efficient rendering.
Correct:
key={index}
Without keys, React shows warnings.
Adding Delete Functionality
Now let’s allow users to remove tasks.
Delete Function
const deleteTask = (indexValue) => {
const updatedTasks =
tasks.filter(
(item, index) =>
index !== indexValue
);
setTasks(updatedTasks);
};
Add Delete Button
<button
onClick={() =>
deleteTask(index)
}
>
Delete
</button>
Complete Task List
{tasks.map((item, index) => (
<div key={index}>
<h3>{item}</h3>
<button
onClick={() =>
deleteTask(index)
}
>
Delete
</button>
</div>
))}
How Delete Function Works?
Step 1
User clicks delete button.
Step 2
filter() removes selected task.
Step 3
State updates.
Step 4
React updates UI automatically.
Adding Complete Task Feature
Now let’s add completed task functionality.
Updated Task Structure
Instead of storing strings:
Instead of storing strings:
["Study", "Code"]
store objects:
[
{
text: "Study",
completed: false
}
]
Updated Add Task
etTasks([
...tasks,
{
text: task,
completed: false
}
]);
Toggle Complete Function
const toggleComplete = (indexValue) => {
const updatedTasks =
[...tasks];
updatedTasks[indexValue].completed =
!updatedTasks[indexValue].completed;
setTasks(updatedTasks);
};
Updated Rendering
{tasks.map((item, index) => (
<div key={index}>
<h3
style={{
textDecoration:
item.completed
? "line-through"
: "none"
}}
>
{item.text}
</h3>
<button
onClick={() =>
toggleComplete(index)
}
>
Complete
</button>
</div>
))}
How Complete Feature Works?
Step 1
Button click triggers function.
Step 2
completed value changes.
Step 3
Conditional styling updates UI.
Adding CSS Styling
App.css
body {
font-family: Arial;
text-align: center;
margin-top: 50px;
}
input {
padding: 10px;
width: 250px;
}
button {
padding: 10px;
margin-left: 10px;
cursor: pointer;
}
Final Todo App Features
Our Todo App now supports:
- Adding tasks
- Displaying tasks
- Deleting tasks
- Marking completed tasks
Real-Life Example of Todo App
Todo apps are used in:
- Daily planning
- Team management
- Project tracking
- Productivity tools
Common Mistakes While Building Todo App
1. Mutating State Directly
Wrong:
tasks.push(task);
Correct:
setTasks([...tasks, task]);
2. Missing key Prop
Wrong:
<div>
Correct:
<div key={index}>
3. Forgetting useState
Without state, UI won’t update dynamically.
4. Not Clearing Input Field
Always reset input after adding task.
setTask("");
Improving Todo App
After building basic Todo App, you can add:
Local Storage
Save tasks permanently.
Edit Task Feature
Allow task editing.
Search Feature
Search tasks quickly.
Filter Tasks
Show:
- Completed tasks
- Pending tasks
Dark Mode
Improve UI experience.
React Router
Create multiple pages.
Todo App with Local Storage
You can store tasks permanently using:
localStorage.setItem(
"tasks",
JSON.stringify(tasks)
);
Fetch Tasks from Local Storage
const savedTasks =
JSON.parse(
localStorage.getItem("tasks")
);
Why Todo App is Important for Beginners?
Todo App teaches:
- Component structure
- State updates
- React Hooks
- Dynamic rendering
- CRUD concepts
It is one of the best beginner React projects.
Performance Optimization Tips
Use React.memo
Prevents unnecessary renders.
Use Unique IDs
Avoid using array index when possible.
Split Components
Create:
- TodoForm
- TodoList
- TodoItem
for cleaner architecture.
Conclusion
A Todo App is one of the best beginner React projects because it combines multiple React concepts into one practical application.
Building projects like Todo Apps improves:
- React understanding
- Problem-solving skills
- Frontend development confidence