In this article, we will explore how to perform CRUD (Create, Read, Update, Delete) operations in a full-stack web application using React, Express.js, and MongoDB. We will provide a detailed explanation of the code and its components, ensuring you understand how each part of the application works.
Prerequisites
Before you start, make sure you have the following installed:
Node.js and npm
MongoDB
Code editor of your choice (e.g., Visual Studio Code)
Setting Up the Backend (Express.js and MongoDB)
Let's start with the backend part of our application, which is responsible for handling database operations.
Express.js Setup
We begin by setting up an Express.js server:
require("dotenv").config();
const express = require("express");
const { MongoClient, ServerApiVersion, ObjectId } = require("mongodb");
const app = express();
const cors = require("cors");
const port = 3000;
app.use(cors());
app.use(express.json());
Here, we import the necessary libraries and initialize the Express application, configure CORS to allow cross-origin requests, and specify the port the server will run on.
MongoDB Connection
Next, we establish a connection to the MongoDB database:
const client = new MongoClient(process.env.MONGO_URL, {
serverApi: {
version: ServerApiVersion.v1,
strict: true,
deprecationErrors: true,
},
});
async function run() {
try {
// Connect to the MongoDB server
await client.connect();
// Access a specific database and collection
const database = client.db("insertDB");
const databaseCollection = database.collection("firstProject");
// Define routes for CRUD operations
// ...
} finally {
// Close the MongoDB client when done
}
}
run().catch(console.dir);
We create an asynchronous function run
to manage the MongoDB connection and handle errors. Inside this function, we connect to the MongoDB server, specify the database and collection we want to work with, and define routes for performing CRUD operations.
CRUD Operations
Now, let's break down the CRUD operations in Express.js:
Read (GET) - Fetch All Users
app.get("/users", async (req, res) => {
const data = databaseCollection.find();
const result = await data.toArray();
res.send(result);
});
This route retrieves all user records from the MongoDB collection and sends them as a response.
Read (GET) - Fetch a Single User by ID
app.get("/users/:id", async (req, res) => {
const id = req.params.id;
const query = { _id: new ObjectId(id) };
const user = await databaseCollection.findOne(query);
res.send(user);
});
This route fetches a single user record by its unique ID.
Create (POST) - Add a User
app.post("/user", async (req, res) => {
const data = req.body;
const doc = {
user: data.user,
email: data.email,
};
const result = await databaseCollection.insertOne(doc);
res.send(result);
});
This route adds a new user to the collection.
Update (PUT) - Update a User by ID
app.put("/user/:id", async (req, res) => {
const data = req.body;
const paramsId = req.params.id;
const filter = { _id: new ObjectId(paramsId) };
const options = { upsert: true };
const updateDoc = {
$set: {
user: data.user,
email: data.email,
},
};
const result = await databaseCollection.updateOne(filter, updateDoc, options);
res.send(result);
});
This route updates an existing user record based on its unique ID.
Delete (DELETE) - Delete a User by ID
app.delete("/user/:id", async (req, res) => {
const id = req.params.id;
const query = { _id: new ObjectId(id) };
const result = await databaseCollection.deleteOne(query);
res.send(result);
});
This route deletes a user record by its unique ID.
Server Initialization
Lastly, we start the Express.js server:
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
Setting Up the Frontend (React)
Now, let's move to the frontend part of our application, which is built using React. We will explore how to create, read, update, and delete user data in the React application.
React Router
We use React Router to handle navigation and routing within our React application:
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.jsx";
import "./index.css";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import Get from "./components/Get.jsx";
import Update from "./components/Update.jsx";
const router = createBrowserRouter([
{
path: "/add",
element: <App />,
},
{
path: "/",
element: <Get />,
},
{
path: "/update/:id",
element: <Update />,
},
]);
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>
);
Here, we configure routing for three main pages: adding a user, viewing all users, and updating a user.
Adding a User
In the App.jsx
component, we create a form to add a new user:
import "./App.css";
function App() {
const handleSubmit = (e) => {
e.preventDefault();
const form = e.target;
const email = form.email.value;
const user = form.user.value;
const sendData = { user, email };
fetch("http://localhost:3000/user", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(sendData),
})
.then((res) => res.json())
.then((data) => {
if (data.acknowledged === true) {
alert("Saved Successfully");
}
form.reset();
});
};
return (
<div>
<form onSubmit={handleSubmit}>
<input type="email" name="email" placeholder="Email" />
<input type="text" name="user" placeholder="User" />
<input type="submit" name="" id="" />
</form>
</div>
);
}
export default App;
This component defines a form to input user details and sends a POST request to the server to add the user to the database.
Viewing All Users
In the Get.jsx
component, we retrieve and display all user records:
import { useEffect, useState } from "react";
import { Link } from "react-router-dom";
const Get = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch("http://localhost:3000/users")
.then((res) =>
res.json())
.then((data) => setUsers(data));
}, []);
const handleDelete = (id) => {
fetch(`http://localhost:3000/user/${id}`, {
method: "DELETE",
})
.then((res) => res.json())
.then((data) => {
if (data.deletedCount > 0) {
alert("Deleted Successfully");
const remaining = users.filter((user) => user._id !== id);
setUsers(remaining);
}
});
};
return (
<div>
<h1>Users: {users.length}</h1>
{users.map((user) => (
<p key={user._id}>
{user.user} - {user.email}
<Link to={`/update/${user._id}`}>
<button>Update</button>
</Link>
<button onClick={() => handleDelete(user._id)}>Delete</button>
</p>
))}
</div>
);
};
export default Get;
This component fetches and displays all user records and provides options to update or delete each user.
Updating a User
In the Update.jsx
component, we enable users to update their information:
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
const Update = () => {
const params = useParams();
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`http://localhost:3000/users/${params.id}`)
.then((res) => res.json())
.then((data) => setUser(data));
}, [params]);
const handleSubmit = (e) => {
e.preventDefault();
const form = e.target;
const email = form.email.value;
const user = form.user.value;
fetch(`http://localhost:3000/user/${params.id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ user, email }),
});
};
return (
<div>
<form onSubmit={handleSubmit}>
<input type="email" name="email" defaultValue={user?.email} />
<input type="text" name="user" defaultValue={user?.user} />
<input type="submit" />
</form>
</div>
);
};
export default Update;
This component retrieves user details, allows users to modify their data, and sends a PUT request to update the information.
Conclusion
In this article, we've covered the full-stack development of a React-Express-MongoDB application, demonstrating how to perform CRUD operations. We've explored the backend setup using Express.js and MongoDB, and the frontend development using React with React Router.
Understanding this code and the integration between the server and the client is crucial for building modern web applications. You can use this foundation to create more complex web applications and enhance your skills in web development.