How to Create a To-Do List with React
To-do lists are an essential tool for organizing day-to-day tasks. With React, one of the most popular JavaScript libraries for building user interfaces, we can create a dynamic and interactive To-Do List. In this tutorial, we'll guide you through the process of creating a simple To-Do List using React, from the initial setup to implementing basic functionalities.
Prerequisites ๐ก
Before we dive into building our To-Do List with React, let's ensure that you have Node.js and npm installed on your machine. Here's how you can verify and install them if needed:
Verifying Node.js and npm Installation
Open your terminal (Command Prompt, PowerShell, or Terminal) and run the following commands:
To check the version of Node.js installed:
node -v
To check the version of npm installed:
npm -v
If both commands return a version number, it means Node.js and npm are already installed on your machine.
Installing Node.js and npm
If Node.js and npm are not installed or if the commands above don't return a version number, follow these steps to install them:
Download the Installer: Visit the official Node.js website at nodejs.org and download the installer for your operating system (Windows, macOS, or Linux).
Install Node.js: Run the downloaded installer and follow the installation instructions. The installation process will automatically install both Node.js and npm.
Verify Installation: Once the installation is complete, open a new terminal window and run the node -v
and npm -v
commands again to verify that Node.js and npm are installed correctly.
Step 1: Setting Up the Environment
Let's start by creating a new React application. Open your terminal and run the following command:
npx create-react-app todo-list
This will create a new folder named todo-list
with the basic structure of the React project.
Step 2: Project Structure
After creating the React application, navigate to the project directory and open it in your preferred code editor. Inside the src
folder, you'll find the main project files. To keep our code organized, let's create three new folders: components
, pages
, and styles
.
todo-list/
โโโ src/
โ โโโ components/
โ โโโ pages/
โ โโโ styles/
Step 3: Creating Components
Inside the components
folder, create two new files: TodoForm.js
and TodoItem.js
. The TodoForm
will be responsible for adding new tasks to the list, while TodoItem
will be responsible for displaying each item in the task list.
TodoItem.js
Let's start by implementing the TodoItem
. Here's a basic example of the code for this component:
// TodoItem.js - https://hashnode.com/@hugotav
import React from 'react'; //1
const TodoItem = ({ todo, toggleTodo }) => { //2
const handleToggle = () => { //3
toggleTodo(todo.id); //4
};
return ( //5, 6 e 7
<div className={`todo-item ${todo.completed ? 'completed' : ''}`}>
<input
type="checkbox"
checked={todo.completed}
onChange={handleToggle}
/>
<p>{todo.text}</p>
</div>
);
};
export default TodoItem; //8
import React from 'react';
: This line imports the React library, which is necessary for creating React components.const TodoItem = ({ todo, toggleTodo }) => {
: This declares a functional component named TodoItem, which accepts two props:todo
andtoggleTodo
. Thetodo
prop represents an individual todo item, and thetoggleTodo
prop is a function used to toggle the completion status of the todo item.const handleToggle = () => {
: This defines a function namedhandleToggle
, which will be called when the checkbox is clicked.toggleTodo(todo.id);
: This calls thetoggleTodo
function, passing the ID of the todo item as an argument. This function is responsible for toggling the completion status of the todo item.<div className={`todo-item ${todo.completed ? 'completed' : ''}`}>
: This creates a element with a CSS class of "todo-item". If the todo item is completed (based on the completed property), the class "completed" will be added to the element, which can be used to apply styling indicating that the todo item is completed.<input type="checkbox" checked={todo.completed} onChange={handleToggle}/>
: This creates a checkbox input field. The checked attribute is set based on the completed property of the todo item. If the todo item iscompleted
, the checkbox will bechecked
. The onChange event handler is set to call thehandleToggle
function when the checkbox is clicked.<p>{todo.text}</p>
: This displays the text content of the todo item inside a<p>
element.export default TodoItem;
: This exports the TodoItem component so that it can be imported and used in other parts of the application.
TodoForm.js
Now, let's implement the TodoForm
. This component will have a text field for adding new tasks to the list.
// TodoForm.js - https://hashnode.com/@hugotav
import React, { useState } from 'react'; //1
const TodoForm = ({ addTodo }) => { //2
const [text, setText] = useState(''); //3
const handleSubmit = (e) => { //4
e.preventDefault();
if (!text.trim()) return;
addTodo(text);
setText('');
}
return ( //5, 6 e 7
<form onSubmit={handleSubmit}>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Add new task"
/>
<button type="submit">Add</button>
</form>
);
}
export default TodoForm; //8
import React, { useState } from 'react';
: This line imports React and theuseState
hook from the React library. TheuseState
hook is used to manage state within functional components.const TodoForm = ({ addTodo }) => {
: This declares a functional component named TodoForm, which accepts a prop namedaddTodo
. This prop is a function used to add a new todo item to the list.const [text, setText] = useState('');
: This line uses theuseState
hook to create a state variable namedtext
, which represents the value of the input field in the form. The initial state is an empty string. ThesetText
function is used to update the value oftext
.const handleSubmit = (e) => { ... }
: This defines a functionhandleSubmit
which is triggered when the form is submitted. It prevents the default form submission behavior, checks if the input field is not empty, adds the new todo item using theaddTodo
function, and then resets the input field to an empty string.<form onSubmit={handleSubmit}>
: This creates a form element with anonSubmit
event handler set tohandleSubmit
, so that when the form is submitted, thehandleSubmit
function is called.<input type="text" value={text} onChange={(e) => setText(
e.target
.value)} placeholder="Add new task" />
: This creates a text input field. The value of the input is controlled by thetext
state variable. When the input value changes, theonChange
event updates thetext
state using thesetText
function.<button type="submit">Add</button>
: This creates a submit button for the form.export default TodoForm;
: This exports the TodoForm component so that it can be imported and used in other parts of the application.
Step 4: Implementing the Task List
Inside the pages
folder, create a new file named TodoPage.js
. This file will be responsible for managing the state of the task list and rendering the TodoForm
and TodoItem
components.
// TodoPage.js - https://hashnode.com/@hugotav
import React, { useState } from 'react';
import TodoForm from '../components/TodoForm'; // Importing TodoForm component from TodoForm.js file
import TodoItem from '../components/TodoItem'; // Importing TodoItem component from TodoItem.js file
import '../styles/TodoStyles.css'; // Importing CSS styles for TodoPage
// Declaring functional component TodoPage
const TodoPage = () => {
// Declaring state variable 'todos' and function 'setTodos' using useState hook
const [todos, setTodos] = useState([]); // Initial state is an empty array
// Function to add a new todo item to the list
const addTodo = (text) => {
const newTodo = { id: Date.now(), text, completed: false }; // Creating a new todo object with unique ID, provided text, and initial completion status
setTodos([...todos, newTodo]); // Updating the state by adding the new todo item to the existing list of todos
}
// Function to toggle the completion status of a todo item
const toggleTodo = (id) => {
// Mapping over the existing todos array and toggling the completion status of the todo item with the specified ID
const updatedTodos = todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
);
setTodos(updatedTodos); // Updating the state with the updated todo list
}
// Rendering JSX (JavaScript XML) to represent the TodoPage component
return (
<div className="todo-page"> {/* Container div with class name "todo-page" */}
<h1>To-Do List</h1> {/* Heading for the todo list */}
<TodoForm addTodo={addTodo} /> {/* Rendering TodoForm component and passing addTodo function as prop */}
<div className="todo-list"> {/* Container div for displaying todo items */}
{todos.map(todo => (
<TodoItem key={todo.id} todo={todo} toggleTodo={toggleTodo} />
))} {/* Mapping over the todo list and rendering TodoItem component for each todo item */}
</div>
<div className='todo-credits'> {/* Container div for displaying credits */}
<a href='https://hashnode.com/@hugotav'>By Hugo Tavares</a> {/* Link to the author's profile */}
</div>
</div>
);
}
export default TodoPage; // Exporting TodoPage component for use in other files
Step 5: Styling the Application
Finally, let's style our application. Inside the styles
folder, create a file named TodoStyles.css
and add CSS styles for the components.
/* TodoStyles.css - https://hashnode.com/@hugotav */
.todo-page {
max-width: 400px;
margin: 0 auto;
padding: 20px;
background-color: #f4f4f4;
border-radius: 8px;
}
.todo-page h1{
text-align: center;
}
.todo-item {
display: flex;
align-items: center;
margin-bottom: 0px;
}
.todo-item p {
margin-left: 8px;
}
.todo-item input[type="checkbox"] {
margin-right: 8px;
}
.completed {
text-decoration: line-through;
color: #888;
}
.completed input[type="checkbox"] {
opacity: 0.5;
}
.todo-list {
margin-top: 0px;
margin-bottom: 0px;
}
.todo-credits {
margin-top: 20px;
align-items: center;
text-align: center;
font-size: smaller;
font-weight: bold;
}
.todo-credits a {
text-decoration: none;
}
Viewing Your Work ๐
After following all the steps to create your Todo List with React, you'll be ready to view your work. To do this, the key command is npm start
, which starts the development server and opens your React application in a web browser.
Running the Application
Make sure you're in the directory of your project in the terminal. Then, execute the command:
npm start
This will start the development server and compile your React application. Once the compilation is complete, your default browser will automatically open, and you'll see your Todo List in action.
Accessing the React Page
If the browser doesn't open automatically, you can manually access your application by typing the following address into the browser's address bar:
http://localhost:3000
This will open the home page of your React application, where you can interact with your Todo List, add new tasks, mark tasks as completed, and more.
Keeping the Server Running
While you're working on your project, the development server will be running, and any changes you make to the files will automatically be reflected in the browser without needing to restart the server.
Shutting Down the Server
When you're finished working on your application, you can shut down the development server by pressing Ctrl + C
in the terminal where the server is running.
With this, you'll have full control over your React application and can view and test your work as you progress in developing your Todo List.
Now that you've learned how to view and access your React application, you're ready to create your own Todo List and explore all the potential that React has to offer!
Conclusion โ
Now that we've implemented our basic To-Do List with React and added the functionality to mark tasks as completed, the possibilities for expansion are endless. You can further enhance your application by adding features like task deletion, filtering tasks by completion status, or even integrating with a database to save tasks persistently.
This tutorial has provided you with a solid foundation to start creating your own applications with React. Whether you're building a simple to-do list or a complex web application, React offers the flexibility and power to bring your ideas to life. I hope you found this tutorial helpful, and I can't wait to see what you create next! ๐
Subscribe to my newsletter
Read articles from Hugo Tavares directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Hugo Tavares
Hugo Tavares
Hello World, my name is Hugo. Iโm a Christian, husband, and father. I hold a degree in Administration and have experience in the military as an air traffic controller. Additionally, Iโm a frontend developer, fascinated by technology, and constantly seeking to learn new things.