DEV Community

Cover image for Performing CRUD Operations in a React-Express-MongoDB Application
Jack Pritom Soren
Jack Pritom Soren

Posted on

Performing CRUD Operations in a React-Express-MongoDB Application

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());
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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);
});
Enter fullscreen mode Exit fullscreen mode

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);
});
Enter fullscreen mode Exit fullscreen mode

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);
});
Enter fullscreen mode Exit fullscreen mode

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);
});
Enter fullscreen mode Exit fullscreen mode

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);
});
Enter fullscreen mode Exit fullscreen mode

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}`);
});
Enter fullscreen mode Exit fullscreen mode

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>
);
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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.

Follow me on : Github Linkedin

Top comments (0)