The MERN stack (MongoDB, Express.js, React.js, Node.js) is a powerful combination of technologies for building modern, full-stack web applications using JavaScript. A CRUD (Create, Read, Update, Delete) app is a basic yet essential application structure for handling data in web development. In this guide, we will walk through the process of building a simple CRUD app using the MERN stack, where users can create, read, update, and delete records in a database.
By the end of this tutorial, you'll understand how to set up the backend and frontend of a MERN stack application, create API endpoints, connect the app to a MongoDB database, and build an interactive user interface with React.
First, let's organize our project into a backend and frontend directory:
my-mern-app/
├── backend/ # Node.js and Express API
└── frontend/ # React app
Initialize the backend:
Inside the backend
folder, run the following command to initialize a Node.js project:
npm init -y
Install dependencies:
We will need the following npm packages:
npm install express mongoose cors body-parser
Create the server (server.js):
In backend/server.js
, set up the Express server and connect to MongoDB using Mongoose.
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const bodyParser = require('body-parser');
const app = express();
const PORT = 5000;
// Middleware
app.use(cors());
app.use(bodyParser.json());
// MongoDB connection
mongoose.connect('mongodb://localhost:27017/merncrud', {
useNewUrlParser: true,
useUnifiedTopology: true,
}).then(() => {
console.log('MongoDB connected');
}).catch((err) => {
console.log('Error connecting to MongoDB', err);
});
// Start the server
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Create the Model (Item.js):
In the backend/models
folder, create a Item.js
file to define the data schema.
const mongoose = require('mongoose');
const itemSchema = new mongoose.Schema({
name: { type: String, required: true },
description: { type: String, required: true },
});
const Item = mongoose.model('Item', itemSchema);
module.exports = Item;
Create the Routes (itemRoutes.js):
Create the API routes for CRUD operations in backend/routes/itemRoutes.js
.
const express = require('express');
const Item = require('../models/Item');
const router = express.Router();
// Create an item
router.post('/items', async (req, res) => {
const { name, description } = req.body;
const newItem = new Item({ name, description });
try {
await newItem.save();
res.status(201).send(newItem);
} catch (err) {
res.status(400).json({ message: 'Error creating item', error: err });
}
});
// Read all items
router.get('/items', async (req, res) => {
try {
const items = await Item.find();
res.status(200).json(items);
} catch (err) {
res.status(400).json({ message: 'Error fetching items', error: err });
}
});
// Update an item
router.put('/items/:id', async (req, res) => {
const { id } = req.params;
const { name, description } = req.body;
try {
const updatedItem = await Item.findByIdAndUpdate(id, { name, description }, { new: true });
res.status(200).json(updatedItem);
} catch (err) {
res.status(400).json({ message: 'Error updating item', error: err });
}
});
// Delete an item
router.delete('/items/:id', async (req, res) => {
const { id } = req.params;
try {
await Item.findByIdAndDelete(id);
res.status(200).send('Item deleted');
} catch (err) {
res.status(400).json({ message: 'Error deleting item', error: err });
}
});
module.exports = router;
Use Routes in the Server:
In backend/server.js
, import and use the routes:
const itemRoutes = require('./routes/itemRoutes');
app.use('/api', itemRoutes);
Initialize the frontend:
Create the React app in the frontend
folder:
npx create-react-app frontend
cd frontend
Install Axios:
Axios is used to make HTTP requests to the backend API.
npm install axios
Create the CRUD Components:
Create a CRUDApp.js
component that will display and handle the CRUD operations. For example:
import React, { useState, useEffect } from 'react';
import axios from 'axios';
function CRUDApp() {
const [items, setItems] = useState([]);
const [newItem, setNewItem] = useState({ name: '', description: '' });
useEffect(() => {
fetchItems();
}, []);
const fetchItems = async () => {
const res = await axios.get('http://localhost:5000/api/items');
setItems(res.data);
};
const handleCreate = async () => {
await axios.post('http://localhost:5000/api/items', newItem);
fetchItems();
};
const handleDelete = async (id) => {
await axios.delete(`http://localhost:5000/api/items/${id}`);
fetchItems();
};
return (
<div>
<h1>CRUD App</h1>
<input
type="text"
placeholder="Name"
value={newItem.name}
onChange={(e) => setNewItem({ ...newItem, name: e.target.value })}
/>
<input
type="text"
placeholder="Description"
value={newItem.description}
onChange={(e) => setNewItem({ ...newItem, description: e.target.value })}
/>
<button onClick={handleCreate}>Add Item</button>
<ul>
{items.map(item => (
<li key={item._id}>
{item.name} - {item.description}
<button onClick={() => handleDelete(item._id)}>Delete</button>
</li>
))}
</ul>
</div>
);
}
export default CRUDApp;
Run Both Frontend and Backend:
node server.js
in the backend
folder.npm start
in the frontend
folder.Building a full-stack CRUD app using the MERN stack involves mastering backend development with Node.js, Express, and MongoDB, as well as frontend development with React.js. This combination of technologies allows you to create a dynamic and interactive application where users can perform CRUD operations on data. By following the steps outlined in this tutorial, you’ve learned how to set up a MERN stack application from scratch, handle API requests, manage data, and display it on the frontend.