Introduction.
A Todo list is one of those classic beginner projects that never gets old, especially in React.
It’s simple yet powerful. You get to play around with components, manage state, and gain a better understanding of how React works under the hood.
In this article, I’ll walk through how to create a fully functional Todo list app using React JS.
1. Setting Up the Project.
Before diving into code, let’s set up the environment.
- Install Node.js: If you haven’t already, install Node.js from here. Node comes with npm (Node Package Manager), which is necessary for installing React and other dependencies.
- Create a New React App: Using Create React App, which is the easiest way to get started, run the following in your terminal:
npx create-react-app todo-list
cd todo-list
npm start
This will create a basic boilerplate React app and start the development server on http://localhost:3000.
2.Structuring the Todo App.
For this Todo app, I’ll need a few components:
- App Component: The root component that wraps everything together.
- Todo Component: Displays each individual Todo item.
- TodoForm Component: A form for adding new Todos.
- TodoList Component: A list that renders all Todo items.
Let's start building these step by step.
1. App Component.
The App component is the main container. I’ll import the other components into this one.
import React, { useState } from "react";
import TodoList from "./TodoList";
import TodoForm from "./TodoForm";
function App() {
const [todos, setTodos] = useState([]);
const addTodo = (todo) => {
if (!todo.text || /^\s*$/.test(todo.text)) {
return;
}
const newTodos = [todo, ...todos];
setTodos(newTodos);
};
return (
<div className="App">
<h1>Todo List</h1>
<TodoForm addTodo={addTodo} />
<TodoList todos={todos} />
</div>
);
}
export default App;
In the above code, I’m using React’s useState hook to manage an array of Todo items. addTodo is a function that takes a new Todo and updates the state.
2. TodoForm Component
Next, I need a form where users can type in new Todos.
import React, { useState } from "react";
function TodoForm({ addTodo }) {
const [input, setInput] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
addTodo({
id: Math.floor(Math.random() * 10000),
text: input,
isComplete: false,
});
setInput("");
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Add a todo"
value={input}
onChange={(e) => setInput(e.target.value)}
/>
<button>Add Todo</button>
</form>
);
}
export default TodoForm;
This component includes a simple form with an input field and a button. I’m using useState to manage the form input, and handleSubmit will call the addTodo function passed down as a prop from the App component.
3. TodoList Component.
Now, I need a component that renders all Todos.
import React from "react";
import Todo from "./Todo";
function TodoList({ todos }) {
return (
<div>
{todos.map((todo, index) => (
<Todo key={index} todo={todo} />
))}
</div>
);
}
export default TodoList;
Here, the TodoList component receives the todos array as a prop and maps through each Todo to render a Todo component.
4. Todo Component.
Finally, here’s the Todo item itself.
import React from "react";
function Todo({ todo }) {
return (
<div>
<div>{todo.text}</div>
</div>
);
}
export default Todo;
The Todo component is very simple. It just displays the text of the Todo item passed to it as a prop.
Adding Additional Features
Marking Todos as Complete: To make the app more useful, I’ll add functionality for marking a Todo as complete. I can add a new function in the App component to handle this:
const completeTodo = (id) => {
let updatedTodos = todos.map((todo) => {
if (todo.id === id) {
todo.isComplete = !todo.isComplete;
}
return todo;
});
setTodos(updatedTodos);
};
Then, pass completeTodo as a prop to the Todo component.
function Todo({ todo, completeTodo }) {
return (
<div>
<div onClick={() => completeTodo(todo.id)}>{todo.text}</div>
</div>
);
}
Clicking a Todo will now toggle its completion status.
Deleting Todos: I can also add a delete function.
const removeTodo = (id) => {
const updatedTodos = todos.filter((todo) => todo.id !== id);
setTodos(updatedTodos);
};
This function filters out the Todo with the matching id, and I can again pass this down as a prop to Todo:
function Todo({ todo, removeTodo }) {
return (
<div>
<div>{todo.text}</div>
<button onClick={() => removeTodo(todo.id)}>Delete</button>
</div>
);
}
Pros and Cons of Building a Todo App in React
Pros:
- Simple and Effective: A Todo list is a great entry-level project that helps in grasping key React concepts without overwhelming you.
- State Management: Working with useState and passing state between components is a fantastic way to learn how to handle dynamic data in React.
- Component-Based Structure: It’s easy to scale and add features like editing, filtering, and local storage.
- Reusable Logic: You can reuse components, making the project scalable and modular.
Cons:
- Basic Scope: While a Todo list teaches core concepts, it can quickly feel too simplistic if you’re aiming for something more complex.
- Limited Real-World Application: Building a Todo app in React is great for learning, but in terms of practical use, it’s a small project compared to what’s often required in larger applications.
- State Complexity Grows: As you add more features (e.g., filtering, sorting, etc.), state management can become more complex and challenging without using something like Redux or Context API.
Conclusion.
Creating a Todo list in React is more than just building a simple app—it’s a powerful way to solidify your understanding of components, state, and props.
Once you grasp these basics, you'll find yourself much more comfortable tackling larger, more complex React applications.
So, what feature would you add next to take this Todo list to the next level?
Top comments (0)