
Build a CRUD App with React, Node.js & MongoDB
Creating a full-stack CRUD (Create, Read, Update, Delete) application using React for the frontend, Node.js and Express for the backend, and MongoDB for the database is a common and practical project. It helps you understand how to connect the client and server, handle HTTP requests, and manage data persistently.
In this tutorial, we will create a simple task management app that allows users to create, view, update, and delete tasks.
1. Project Structure Overview
crud-app/
├── client/ (React frontend)
├── server/ (Node.js backend)
└── README.md
2. Setting Up the Backend (Node.js + Express + MongoDB)
2.1 Initialize the Backend
mkdir server && cd server
npm init -y
npm install express mongoose cors dotenv
2.2 Create Server Files
server/
├── models/
│ └── Task.js
├── routes/
│ └── tasks.js
├── .env
├── server.js
2.3 Configure MongoDB Connection (.env)
MONGO_URI=mongodb://localhost:27017/cruddb
PORT=5000
2.4 Define the Task Model (models/Task.js)
const mongoose = require('mongoose');
const taskSchema = new mongoose.Schema({
title: { type: String, required: true },
completed: { type: Boolean, default: false }
});
module.exports = mongoose.model('Task', taskSchema);
2.5 Define Routes (routes/tasks.js)
const express = require('express');
const router = express.Router();
const Task = require('../models/Task');
// CREATE
router.post('/', async (req, res) => {
try {
const task = new Task(req.body);
await task.save();
res.status(201).json(task);
} catch (error) {
res.status(400).json({ error: error.message });
}
});
// READ
router.get('/', async (req, res) => {
try {
const tasks = await Task.find();
res.json(tasks);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// UPDATE
router.put('/:id', async (req, res) => {
try {
const task = await Task.findByIdAndUpdate(req.params.id, req.body, { new: true });
res.json(task);
} catch (error) {
res.status(400).json({ error: error.message });
}
});
// DELETE
router.delete('/:id', async (req, res) => {
try {
await Task.findByIdAndDelete(req.params.id);
res.json({ message: 'Task deleted' });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
module.exports = router;
2.6 Setup Express Server (server.js)
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const dotenv = require('dotenv');
const taskRoutes = require('./routes/tasks');
dotenv.config();
const app = express();
app.use(cors());
app.use(express.json());
mongoose.connect(process.env.MONGO_URI)
.then(() => console.log('MongoDB connected'))
.catch(err => console.error(err));
app.use('/api/tasks', taskRoutes);
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
3. Setting Up the Frontend (React)
3.1 Initialize React App
cd ..
npx create-react-app client
cd client
npm install axios
3.2 Create React Component Structure
client/src/
├── components/
│ ├── TaskForm.js
│ ├── TaskList.js
├── App.js
├── index.js
3.3 TaskForm Component
import React, { useState, useEffect } from 'react';
import axios from 'axios';
function TaskForm({ fetchTasks, editingTask, setEditingTask }) {
const [title, setTitle] = useState('');
useEffect(() => {
if (editingTask) setTitle(editingTask.title);
}, [editingTask]);
const handleSubmit = async (e) => {
e.preventDefault();
if (editingTask) {
await axios.put(`/api/tasks/${editingTask._id}`, { title });
setEditingTask(null);
} else {
await axios.post('/api/tasks', { title });
}
setTitle('');
fetchTasks();
};
return (
<form onSubmit={handleSubmit}>
<input value={title} onChange={(e) => setTitle(e.target.value)} placeholder="Enter task" />
<button type="submit">{editingTask ? 'Update' : 'Add'}</button>
</form>
);
}
export default TaskForm;
3.4 TaskList Component
import React from 'react';
import axios from 'axios';
function TaskList({ tasks, fetchTasks, setEditingTask }) {
const handleDelete = async (id) => {
await axios.delete(`/api/tasks/${id}`);
fetchTasks();
};
const handleToggle = async (task) => {
await axios.put(`/api/tasks/${task._id}`, { ...task, completed: !task.completed });
fetchTasks();
};
return (
<ul>
{tasks.map(task => (
<li key={task._id}>
<span style={{ textDecoration: task.completed ? 'line-through' : 'none' }}>{task.title}</span>
<button onClick={() => handleToggle(task)}>Toggle</button>
<button onClick={() => setEditingTask(task)}>Edit</button>
<button onClick={() => handleDelete(task._id)}>Delete</button>
</li>
))}
</ul>
);
}
export default TaskList;
3.5 App Component
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import TaskForm from './components/TaskForm';
import TaskList from './components/TaskList';
function App() {
const [tasks, setTasks] = useState([]);
const [editingTask, setEditingTask] = useState(null);
const fetchTasks = async () => {
const res = await axios.get('/api/tasks');
setTasks(res.data);
};
useEffect(() => {
fetchTasks();
}, []);
return (
<div>
<h1>Task Manager</h1>
<TaskForm fetchTasks={fetchTasks} editingTask={editingTask} setEditingTask={setEditingTask} />
<TaskList tasks={tasks} fetchTasks={fetchTasks} setEditingTask={setEditingTask} />
</div>
);
}
export default App;
4. Final Steps
- Ensure MongoDB is running locally (
mongod
) - Start backend:
cd server node server.js
- Start frontend:
cd client npm start
5. Conclusion
You’ve now built a full-stack CRUD application using the MERN (MongoDB, Express, React, Node.js) stack. This project gives you hands-on experience with connecting a React frontend to a Node.js backend, persisting data with MongoDB, and performing all CRUD operations.
To extend this project further, you can:
- Add user authentication
- Use Redux or Context API for state management
- Deploy using platforms like Render, Vercel, or Heroku
- Add form validation and error handling

I’m Shreyash Mhashilkar, an IT professional who loves building user-friendly, scalable digital solutions. Outside of coding, I enjoy researching new places, learning about different cultures, and exploring how technology shapes the way we live and travel. I share my experiences and discoveries to help others explore new places, cultures, and ideas with curiosity and enthusiasm.