React is a popular JavaScript library for building interactive user interfaces. Creating a todo app teaches you how to structure components, manage state, and handle user input. These are all essential skills for working with React.
Let’s jump into it and see how to set up our project. This requires you to have a basic understanding of reactjs and its JSX syntax. Learn the basics of react & JSX syntax in detail here. Make sure that you’re comfortable with react functional components because this is now standard and we’ll use functional components in our react todo app.
Project Goal
- Build a to-do app where users can add tasks
- mark them as complete
- and delete tasks.
Prerequisites
Basic knowledge of Reactjs is required to build this app.
1) Setting Up the Development Environment
To get started, make sure you have Node.js installed on your machine. Node.js includes npm (Node Package Manager), which allows you to install libraries and tools like React.
1) Initialize a New React Project by running the below command In your terminal, run:
npm create vite@latest my-react-app -- --template react
ShellScript2) Navigate to Your Project Directory
cd my-react-app
ShellScript3) Start the Development Server
npm run dev
ShellScriptYour project should now be up and running on http://localhost:5173
.
Why we are not using create-react-app command, but vite? Because the app installed using create-react-app (webpack) is too slow and lacks many features that Vite provides. You can check the complete head-to-head comparison of both vite & webpack (using create-react-app).
2) Creating the App Structure
In React, our application is divided into smaller re-useable components. For our Todo App, we need to create these components.
- App Component: The main component that houses the entire app.
- ToDoList Component: A container for our list of to-dos.
- ToDoItem Component: Represents each individual to-do item.
- ToDoForm Component: A form for adding new to-dos.
3) Building the To-Do Components
Let’s start building our Todo components
1) App Component (app.jsx
)
The app.jsx
servers as the main component that holds the state of the to-do list.
import React, { useState } from 'react'; import ToDoList from './components/todo-list'; import ToDoForm from './components/todo-form'; function App() { const [todos, setTodos] = useState([]); const addTodo = (text) => { setTodos([...todos, { text, completed: false }]); }; const toggleTodo = (index) => { const newTodos = [...todos]; newTodos[index].completed = !newTodos[index].completed; setTodos(newTodos); }; const deleteTodo = (index) => { const newTodos = [...todos]; newTodos.splice(index, 1); setTodos(newTodos); }; return ( <div className="todo-app"> <h1>React To-Do App</h1> <ToDoForm addTodo={addTodo} /> <ToDoList todos={todos} toggleTodo={toggleTodo} deleteTodo={deleteTodo} /> </div> ); } export default App;
JSX2) ToDoForm Component
The form component allows users to add a new todo.
import React, { useState } from "react"; function ToDoForm({ addTodo }) { const [value, setValue] = useState(""); const handleSubmit = (e) => { e.preventDefault(); if (!value) return; addTodo(value); setValue(""); }; return ( <form onSubmit={handleSubmit}> <input type="text" value={value} onChange={(e) => setValue(e.target.value)} placeholder="Add a new task" /> <button type="submit">Add</button> </form> ); } export default ToDoForm;
JSX3) ToDoList Component
The list component will render each to-do item, which takes all todo’s from app.jsx
component in the form of props.
import React from "react"; import ToDoItem from "./todo-item"; function ToDoList({ todos, toggleTodo, deleteTodo }) { return ( <ul> {todos.map((todo, index) => ( <ToDoItem key={index} index={index} todo={todo} toggleTodo={toggleTodo} deleteTodo={deleteTodo} /> ))} </ul> ); } export default ToDoList;
JSX4) TodoItem Component
Each to-do item will have a checkbox to mark it as complete and a delete button.
import React from 'react'; function ToDoItem({ todo, index, toggleTodo, deleteTodo }) { return ( <li> <div> <input type="checkbox" checked={todo.completed} onChange={() => toggleTodo(index)} /> <p style={{ textDecoration: todo.completed ? 'line-through' : '' }}> {todo.text} </p> </div> <button onClick={() => deleteTodo(index)}>Delete</button> </li> ); } export default ToDoItem;
JSX5) Styling the To-Do App
You can add some simple CSS to enhance the app’s appearance. Create a main.css
file in the src
folder and add the following:
body { font-family: Arial, sans-serif; display: flex; justify-content: center; align-items: center; padding: 50px; } .todo-app { width: 400px; display: flex; flex-direction: column; justify-content: center; align-items: center; } h1 { color: #333; text-align: center; } ul { list-style-type: none; width: 100%; background-color: #f1f1f1; border-radius: 0px; padding: 0 20px; margin-top: 20px; } li { margin: 5px 0; display: flex; align-items: center; justify-content: space-between; } li > div { display: flex; justify-content: center; align-items: center; gap: 10px; } input[type='text'] { padding: 5px; margin-right: 10px; } button { margin-left: 10px; padding: 5px 10px; background-color: #007bff; color: white; border: none; cursor: pointer; } button:hover { background-color: #0056b3; }
CSS6) Testing Your Todo App
After implementing your components, test your todo app to ensure everything functions correctly. Verify that you can:
- Add new todos
- Mark tasks as completed.
- Delete tasks.
You can test the final working example below:
Final Thoughts
Congratulations on building your first React todo app! This project has taught you essential concepts like component structure, state management, and React hooks.
Consider adding more features, such as:
- Persistent Storage: Use
localStorage
to save tasks, so they remain even after refreshing the page. - Edit Task: Allow users to edit an existing to-do.
- Filter Tasks: Add options to filter tasks by status (All, Completed, Pending).