Todo List Application using MERN
Last Updated :
08 Jan, 2025
Todo list web application using MERN stack is a project that basically implements basic CRUD operation using MERN stack (MongoDB, Express JS, Node JS, React JS). The users can read, add, update, and delete their to-do list in the table using the web interface. The application gives a feature to the user to add a deadline to their task so that it user can be reminded of the last day to complete the project
Preview of final output: Let us have a look at how the final application will look like.
Technologies used / Pre-requisites:
Requirements:
Building a Todo List app with MERN is a great way to learn full-stack development.
Approach to create Todo List:
- In frontend, the react component called "Todo" is used to display tasks, deadlines and its status and form to add new todo item with edit and deletion feature.
- In backend, application fetches data from MongoDB using backend API called "/getTodoList". New data can be added to the database using "/addTodoList" API. "/updateTodoList/:id" API is used to edit the existing specific data from the table. "/deleteTodoList/:id" API is used to delete the specific data from the table.
Functionalities Of Todo Application:
- Add new todo: User can add new todo task using the form. On clicking "submit" button, The new data will be saved to database.
- Display todo list: User can view the todo list in table format.
- Edit existing data: User can click on "Edit" button to make the table row to editable fields. On clicking "Edit" button, new buttons call "Save" and "Reset" will be created. "Save" button is to update the edited data to database. "Reset" button is to reset the data in the field.
- Delete existing data: User can click on "Delete" button available in the table row to delete the data from database.
Project Structure:
Todo list project structureSteps to create the project:
Step 1: Create directory for project.
mkdir Todo-List
Step 2: Create sub directories for frontend and backend.
Open Todo-List directory using following command.
cd Todo-List
Create separate directories for frontend and backend.
mkdir frontend
mkdir backend
Use "ls" command to list created folders.
ls
Step 3: Open backend directory using the following command.
cd backend
Step 4: Initialize Node Package Manager using the following command.
npm init
Initialize npm in backendStep 5: Install express, mongoose and cors package in backend using the following command.
npm install express mongoose cors
Step 6: Come back to Todo-List folder (project main folder).
cd ../
Step 7: Open frontend directory using the following command.
cd frontend
Step 8: Create react application in the current directory using the following command.
npx create-react-app .
Step 9: Install bootstrap, axios and react-router-dom package in backend using the following command.
npm install bootstrap axios react-router-dom
Step 10: Open Todo-List using your familiar code editor.
Come back to Todo-List folder (project main folder).
cd ../
If you are using VS code editor, run the following command open VS code in current folder.
code .
Step 11: Navigate to frontend directory in code editor.
Step 12: Delete files inside 'src' folder and 'public' folder (Don't delete folder).
Step 13: Add files in frontend directory as per the project structure with below code.
Step 14: Navigate to backend directory in code editor.
Step 15: Create server.js and model file as per project structure.
Step 16: Add files in backend directory as per the project structure with below code.
Step 17: Replace database connection URL with your own connection URL in server.js file.
Final Project Structure should be like this,
Project StructureThe updated dependencies in package.json for frontend will look like:
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.5.0",
"bootstrap": "^5.3.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.16.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
}
The updated dependencies in package.json for backend will look like:
"dependencies": {
"cors": "^2.8.5",
"express": "^4.18.2",
"mongoose": "^7.5.2"
}
Example : Write the following code in respective files
Frontend code:
- App.js: This is our main file which routes to the Todo component.
- Todo.js: This component contains all the logic for displaying Tasks, Status of tasks and deadlines of the tasks fetched from database in table format, adding new todo list to database, deleting existing todo from database and editing existing todo in database.
HTML
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>Todo List</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
JavaScript
//App.js
import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import Todo from './components/Todo';
function App() {
const headStyle = {
textAlign: "center",
}
return (
<div>
<h1 style={headStyle}>Todo List</h1>
<BrowserRouter>
<Routes>
<Route path='/' element={<Todo/>}></Route>
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
JavaScript
import axios from "axios";
import React from "react";
import { useEffect, useState } from "react";
function Todo() {
const [todoList, setTodoList] = useState([]);
const [editableId, setEditableId] = useState(null);
const [editedTask, setEditedTask] = useState("");
const [editedStatus, setEditedStatus] = useState("");
const [newTask, setNewTask] = useState("");
const [newStatus, setNewStatus] = useState("");
const [newDeadline, setNewDeadline] = useState("");
const [editedDeadline, setEditedDeadline] = useState("");
// Fetch tasks from database
useEffect(() => {
axios.get('http://127.0.0.1:3001/getTodoList')
.then(result => {
setTodoList(result.data)
})
.catch(err => console.log(err))
}, [])
// Function to toggle the editable state for a specific row
const toggleEditable = (id) => {
const rowData = todoList.find((data) => data._id === id);
if (rowData) {
setEditableId(id);
setEditedTask(rowData.task);
setEditedStatus(rowData.status);
setEditedDeadline(rowData.deadline || "");
} else {
setEditableId(null);
setEditedTask("");
setEditedStatus("");
setEditedDeadline("");
}
};
// Function to add task to the database
const addTask = (e) => {
e.preventDefault();
if (!newTask || !newStatus || !newDeadline) {
alert("All fields must be filled out.");
return;
}
axios.post('http://127.0.0.1:3001/addTodoList', { task: newTask, status: newStatus, deadline: newDeadline })
.then(res => {
console.log(res);
window.location.reload();
})
.catch(err => console.log(err));
}
// Function to save edited data to the database
const saveEditedTask = (id) => {
const editedData = {
task: editedTask,
status: editedStatus,
deadline: editedDeadline,
};
// If the fields are empty
if (!editedTask || !editedStatus || !editedDeadline) {
alert("All fields must be filled out.");
return;
}
// Updating edited data to the database through updateById API
axios.post('http://127.0.0.1:3001/updateTodoList/' + id, editedData)
.then(result => {
console.log(result);
setEditableId(null);
setEditedTask("");
setEditedStatus("");
setEditedDeadline(""); // Clear the edited deadline
window.location.reload();
})
.catch(err => console.log(err));
}
// Delete task from database
const deleteTask = (id) => {
axios.delete('http://127.0.0.1:3001/deleteTodoList/' + id)
.then(result => {
console.log(result);
window.location.reload();
})
.catch(err =>
console.log(err)
)
}
return (
<div className="container mt-5">
<div className="row">
<div className="col-md-7">
<h2 className="text-center">Todo List</h2>
<div className="table-responsive">
<table className="table table-bordered">
<thead className="table-primary">
<tr>
<th>Task</th>
<th>Status</th>
<th>Deadline</th>
<th>Actions</th>
</tr>
</thead>
{Array.isArray(todoList) ? (
<tbody>
{todoList.map((data) => (
<tr key={data._id}>
<td>
{editableId === data._id ? (
<input
type="text"
className="form-control"
value={editedTask}
onChange={(e) => setEditedTask(e.target.value)}
/>
) : (
data.task
)}
</td>
<td>
{editableId === data._id ? (
<input
type="text"
className="form-control"
value={editedStatus}
onChange={(e) => setEditedStatus(e.target.value)}
/>
) : (
data.status
)}
</td>
<td>
{editableId === data._id ? (
<input
type="datetime-local"
className="form-control"
value={editedDeadline}
onChange={(e) => setEditedDeadline(e.target.value)}
/>
) : (
data.deadline ? new Date(data.deadline).toLocaleString() : ''
)}
</td>
<td>
{editableId === data._id ? (
<button className="btn btn-success btn-sm" onClick={() => saveEditedTask(data._id)}>
Save
</button>
) : (
<button className="btn btn-primary btn-sm" onClick={() => toggleEditable(data._id)}>
Edit
</button>
)}
<button className="btn btn-danger btn-sm ml-1" onClick={() => deleteTask(data._id)}>
Delete
</button>
</td>
</tr>
))}
</tbody>
) : (
<tbody>
<tr>
<td colSpan="4">Loading products...</td>
</tr>
</tbody>
)}
</table>
</div>
</div>
<div className="col-md-5">
<h2 className="text-center">Add Task</h2>
<form className="bg-light p-4">
<div className="mb-3">
<label>Task</label>
<input
className="form-control"
type="text"
placeholder="Enter Task"
onChange={(e) => setNewTask(e.target.value)}
/>
</div>
<div className="mb-3">
<label>Status</label>
<input
className="form-control"
type="text"
placeholder="Enter Status"
onChange={(e) => setNewStatus(e.target.value)}
/>
</div>
<div className="mb-3">
<label>Deadline</label>
<input
className="form-control"
type="datetime-local"
onChange={(e) => setNewDeadline(e.target.value)}
/>
</div>
<button onClick={addTask} className="btn btn-success btn-sm">
Add Task
</button>
</form>
</div>
</div>
</div>
)
}
export default Todo;
JavaScript
//index.js - Serves as the entry point for your React application
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App'; // Your main application component
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
Backend:
- Server.js: This is a file which contains logic to start the backend server, APIs to interact with database.
- todoList.js: This is a model file called a wrapper of the Mongoose schema. This file is used to define the schema of table that stores the todo list.
JavaScript
//server.js
const express = require('express')
const mongoose = require('mongoose')
const cors = require('cors')
const TodoModel = require("./models/todoList")
var app = express();
app.use(cors());
app.use(express.json());
// Connect to your MongoDB database (replace with your database URL)
mongoose.connect("mongodb://127.0.0.1/todo");
// Check for database connection errors
mongoose.connection.on("error", (error) => {
console.error("MongoDB connection error:", error);
});
// Get saved tasks from the database
app.get("/getTodoList", (req, res) => {
TodoModel.find({})
.then((todoList) => res.json(todoList))
.catch((err) => res.json(err))
});
// Add new task to the database
app.post("/addTodoList", (req, res) => {
TodoModel.create({
task: req.body.task,
status: req.body.status,
deadline: req.body.deadline,
})
.then((todo) => res.json(todo))
.catch((err) => res.json(err));
});
// Update task fields (including deadline)
app.post("/updateTodoList/:id", (req, res) => {
const id = req.params.id;
const updateData = {
task: req.body.task,
status: req.body.status,
deadline: req.body.deadline,
};
TodoModel.findByIdAndUpdate(id, updateData)
.then((todo) => res.json(todo))
.catch((err) => res.json(err));
});
// Delete task from the database
app.delete("/deleteTodoList/:id", (req, res) => {
const id = req.params.id;
TodoModel.findByIdAndDelete({ _id: id })
.then((todo) => res.json(todo))
.catch((err) => res.json(err));
});
app.listen(3001, () => {
console.log('Server running on 3001');
});
JavaScript
//todoList.js
const mongoose = require('mongoose');
const todoSchema = new mongoose.Schema({
task: {
type: String,
required: true,
},
status: {
type: String,
required: true,
},
deadline: {
type: Date,
},
});
const todoList = mongoose.model("todo", todoSchema);
module.exports = todoList;
Steps to run application:
Step 1: Open Todo-List/backend folder in new terminal / command prompt.
Step 2: Execute the command to start backend API server.
npm start
Now, our backend server is running in localhost on port 3001.
http://localhost:3001/
Step 3: Open Todo-List/frontend folder in another new terminal / command prompt.
Step 4: Execute the following command to run react app.
npm start
Open the browser and navigate to the following link to open the application.
http://localhost:3000/
Output:
Similar Reads
Stock Market Portfolio App using MERN Stack
The Stock Market Portfolio project is a web application that helps to efficiently manage and track stock market investments and portfolios. In this article, we will see a step-wise process of building a Stock Market Portfolio using the power of the MERN stack. Project Preview: Let us have a look at
5 min read
Hospital Management Application using MERN Stack
In the fast-paced world of healthcare, it's vital to manage hospital tasks effectively to ensure top-notch patient care. This article explores creating a strong Hospital Management App using the MERN stack â that's MongoDB, Express, React, and Node.js, breaking down the process for easier understand
15+ min read
Social Media Platform using MERN Stack
In web development, creating a "Social Media Website" will showcase and utilising the power of MERN stack â MongoDB, Express, React, and Node. This application will provide users the functionality to add a post, like the post and able to comment on it. Preview Image: Let us have a look at how the fi
7 min read
Bookstore Ecommerce App using MERN Stack
Bookstore E-commerce project is a great way to showcase your understanding of full-stack development. In this article, we'll walk through the step-by-step process of creating a Bookstore E-commerce using the MERN (MongoDB, Express.js, React, Node.js) stack. This project will showcase how to set up a
8 min read
Chat Website using MERN Stack
The "Chat Website" project is a dynamic web application that is used for real-time communication. The MERN stack, comprised of MongoDB, Express.js, React.js, and Node.js, is a powerful combination of technologies for developing robust and scalable web applications. In this article, we'll explore the
4 min read
Restaurant App using MERN Stack
Creating a Restaurant app will cover a lot of features of the MERN stack. In this tutorial, we'll guide you through the process of creating a restaurant application using the MERN stack. The application will allow users to browse through a list of restaurants, view their menus, and add items to a sh
11 min read
Real Estate Management using MERN
In this article, we will guide you through the process of building a Real Estate Management Application using the MERN stack. MERN stands for MongoDB, Express, React, and Node. MongoDB will serve as our database, Express will handle the backend, React will create the frontend, and Node.js will be th
9 min read
Fruit and Vegetable Market Shop using MERN
In this comprehensive guide, we'll walk through the step-by-step process of creating a Fruit and Vegetable Market Shop using the MERN (MongoDB, Express.js, React, Node.js) stack. This project will showcase how to set up a full-stack web application where users can view, filter, and purchase various
8 min read
Event Management Web App using MERN
In this guide, we'll walk through the step-by-step process of building a feature-rich Event Management Web App. We will make use of the MERN stack to build this project. Preview of final output: Let us have a look at how the final output will look like. PrerequisiteReact JSMongoDBExpressNode JSAppro
9 min read
Expense Tracker (Budget Management) using MERN
An Expense Tracker or Budget Management application using the MERN stack (MongoDB, Express, React, Node) is a powerful and versatile solution for individuals or businesses looking to manage their finances effectively. This stack provides a seamless and efficient way to build a full-fledged web appli
6 min read