Performing CRUD Operations in a React-Express-MongoDB Application
Tags: javascript, react, node, mongodb
Published: 2023-10-28 05:48:30

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:

```javascript
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:

```javascript
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

```javascript
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

```javascript
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

```javascript
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

```javascript
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

```javascript
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:

```javascript
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:

```javascript
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:

```javascript
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:

```javascript
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:

```javascript
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.

Follow me on : [Github](https://github.com/jps27cse) [Linkedin](https://www.linkedin.com/in/jps27cse/)