ebook include PDF & Audio bundle (Micro Guide)
$12.99$7.99
Limited Time Offer! Order within the next:
Building a simple To-Do list application is a classic project for anyone learning software development. It covers fundamental concepts such as user input handling, data storage, dynamic UI updates, and basic CRUD (Create, Read, Update, Delete) operations. While it may appear straightforward, creating a robust, clean, and maintainable To-Do app involves understanding best practices in software architecture, user experience, and state management.
This article will guide you through the process of building a simple To-Do list application from scratch. We'll cover core principles, break down the components of the application, and provide sample code snippets. By the end, you'll not only understand how to create the app but also appreciate the design decisions that go into building scalable, maintainable applications.
Before diving into the technical details, it's important to understand why this project is so valuable:
Before building, we should define what features our app will support:
These features represent the minimal viable product (MVP) for a To-Do app.
You can build a To-Do list app in many environments. Here are some common choices:
For simplicity and broad accessibility, this article focuses on building a web-based To-Do app using React, a popular JavaScript library for building user interfaces. React's component-based architecture and powerful state management capabilities make it ideal for this project.
Use the official React toolchain create-react-app
to scaffold your app quickly.
cd todo-app
npm start
This will launch a development server and open the React starter page in your browser.
The default structure is:
├── public/
├── src/
├── App.js
├── index.js
└── ...
You'll mainly work in the src
folder. Let's clean App.js
by removing the boilerplate content.
Good UI design requires breaking your app into reusable components. For a To-Do list, the main components are:
├── TodoInput
└── TodoList
└── TodoItem (for each task)
App
maintains the list of tasks in its state and provides handler functions to add, toggle, and delete tasks.
import TodoInput from './TodoInput';
import TodoList from './TodoList';
const LOCAL_STORAGE_KEY = 'todoApp.tasks';
function App() {
const [tasks, setTasks] = useState([]);
// Load tasks from localStorage on mount
useEffect(() => {
const storedTasks = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY));
if (storedTasks) setTasks(storedTasks);
}, []);
// Save tasks to localStorage on tasks change
useEffect(() => {
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(tasks));
}, [tasks]);
// Add a new task
const addTask = (taskText) => {
if (!taskText.trim()) return;
const newTask = {
id: Date.now(),
text: taskText,
completed: false,
};
setTasks(prevTasks => [newTask, ...prevTasks]);
};
// Toggle completion status
const toggleTask = (taskId) => {
setTasks(prevTasks =>
prevTasks.map(task =>
task.id === taskId ? { ...task, completed: !task.completed } : task
)
);
};
// Delete a task
const deleteTask = (taskId) => {
setTasks(prevTasks => prevTasks.filter(task => task.id !== taskId));
};
return (
<div className="app-container">
<h1>Simple To-Do List</h1>
<TodoInput addTask={addTask} />
<TodoList tasks={tasks} toggleTask={toggleTask} deleteTask={deleteTask} />
</div>
);
}
export default App;
tasks
is an array of task objects with id
, text
, and completed
properties.useEffect
hooks load and save tasks in browser's localStorage
to persist data.addTask
, toggleTask
, and deleteTask
update the task list appropriately.This component handles user input and submits new tasks.
function TodoInput({ addTask }) {
const [input, setInput] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
addTask(input);
setInput('');
};
return (
<form onSubmit={handleSubmit} className="todo-input-form">
<input
type="text"
placeholder="Enter a new task"
value={input}
onChange={e => setInput(e.target.value)}
className="todo-input"
/>
<button type="submit" className="add-btn">Add</button>
</form>
);
}
export default TodoInput;
addTask
passed from App
.Displays the list of tasks using the TodoItem
component.
import TodoItem from './TodoItem';
function TodoList({ tasks, toggleTask, deleteTask }) {
if (tasks.length === 0) return <p>No tasks yet!</p>;
return (
<ul className="todo-list">
{tasks.map(task => (
<TodoItem
key={task.id}
task={task}
toggleTask={toggleTask}
deleteTask={deleteTask}
/>
))}
</ul>
);
}
export default TodoList;
Represents a single task, allowing toggling and deletion.
function TodoItem({ task, toggleTask, deleteTask }) {
return (
<li className={`todo-item ${task.completed ? 'completed' : ''}`}>
<label>
<input
type="checkbox"
checked={task.completed}
onChange={() => toggleTask(task.id)}
/>
<span>{task.text}</span>
</label>
<button onClick={() => deleteTask(task.id)} className="delete-btn">
Delete
</button>
</li>
);
}
export default TodoItem;
Good styling improves usability and aesthetics. Here's a simple CSS you can add to src/App.css
or a dedicated stylesheet:
max-width: 400px;
margin: 40px auto;
font-family: Arial, sans-serif;
text-align: center;
}
.todo-input-form {
display: flex;
justify-content: center;
margin-bottom: 20px;
}
.todo-input {
width: 70%;
padding: 10px;
font-size: 16px;
}
.add-btn {
padding: 10px 15px;
font-size: 16px;
margin-left: 10px;
cursor: pointer;
}
.todo-list {
list-style: none;
padding: 0;
}
.todo-item {
background: #f4f4f4;
margin: 5px 0;
padding: 10px;
display: flex;
align-items: center;
justify-content: space-between;
}
.todo-item.completed span {
text-decoration: line-through;
color: #888;
}
.delete-btn {
background: #ff4d4d;
border: none;
color: white;
padding: 5px 10px;
cursor: pointer;
}
.delete-btn:hover {
background: #e60000;
}
Once implemented, test the app thoroughly:
While this simple To-Do app works well, here are ways to extend it:
Building a simple To-Do list application is a perfect way to learn core programming concepts and UI design. By structuring the app into components, managing state cleanly, and implementing persistence, you lay a strong foundation for building more complex applications.
You now have a functional React-based To-Do list that supports adding, completing, deleting, and saving tasks. This project can be a springboard into advanced topics like state management libraries (Redux, MobX), backend APIs, and full-stack development.
Happy coding!