How to Build Full Stack MERN CRUD App (React, Node, Express, MongoDB)

Last Updated on by in React JS
A full-stack app contains both frontend and backend components, covering the entire technology stack necessary for building a complete web application. MERN stands for MongoDB, Express, React, Node, these tech stacks are enough to create a full-fledged web application that allow users to perform CRUD operationsIn this ultimate tutorial, we will teach how to create a robust Full-stack MERN CRUD application using React, Node, Express, and MongoDB stack.

In web development, CRUD (Create, Read, Update, and Delete) operations refer to the basic fundamental actions used for managing and manipulating data within a database or application.

React Full Stack MERN CRUD App Example

In this comprehensive guide, we will build a Student management app, this application allows you to add student, show students list, update student, and delete data from the database.

To build the Full stack project, you have to follow given steps.

  • Step 1: Create React Project
  • Step 2: Add Bootstrap in React
  • Step 3: Build Function Components
  • Step 4: Create Routes with React Router
  • Step 5: Build REST API with Node and Express
  • Step 6: Make CRUD HTTP Requests with Axios
  • Step 7: Show Data List with Axios
  • Step 8: Edit, Update and Delete
  • Step 9: Test App on Browser

Create React Application

Let’s start building the React project with create-react-app (CRA).

npx create-react-app react-mernstack-crud

Get inside the React project folder:

cd react-mernstack-crud

Add Bootstrap in React

To build the React js CRUD operations using Node server REST API, we will first install the bootstrap library. The bootstrap package is a boon for making modern React js CRUD project.

npm install bootstrap --legacy-peer-deps

Import library into the src/App.js file and it will help you to create the UI components swiftly.

import "bootstrap/dist/css/bootstrap.min.css";

Open the src/App.css file and add the following code:

.wrapper {
  max-width: 700px;
  margin: 0 auto;
}

Build Function Components

Head over to src folder, make components folder, next we will create the functional components in this directory.

Go to src/components/CreateStudent.js and add the following code.

import React from 'react'

function CreateStudent() {
  return (
    <div></div>
  )
}

export default CreateStudent

Go to src/components/EditStudent.js and add the following code.

import React from 'react'

function EditStudent() {
  return (
    <div></div>
  )
}

export default EditStudent

Go to src/components/StudentList.js and add the following code.

import React from 'react'

function StudentList() {
  return (
    <div></div>
  )
}

export default StudentList

Create Routes with React Router

In order to build a school management app that manages the students data in React through crud operations we need to have routes.

These routes will help us traverse from one point to another point. Install the React Router DOM v6 package using the given command.

npm install react-router-dom@6 --legacy-peer-deps

Next, head over to src/index.js file and tie the App component with the help of <BrowserRouter> object.

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { BrowserRouter } from "react-router-dom";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
);

reportWebVitals();

Next, include the menu in our React CRUD app. Add the given below code in the src/App.js.

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import "./App.css";
import { Routes, Route, Link } from "react-router-dom";
import CreateStudent from "./components/CreateStudent";
import EditStudent from "./components/EditStudent";
import StudentList from "./components/StudentList";

function App() {
  return (
    <div className="App">
      <nav className="navbar navbar-expand-lg bg-body-tertiary">
        <div className="container">
          <Link to={"/create-student"} className="nav-link">
            React MERN Stack App
          </Link>
          <div className="collapse navbar-collapse" id="navbarSupportedContent">
            <ul className="navbar-nav ms-auto mb-2 mb-lg-0">
              <li className="nav-item">
                <Link to={"/create-student"} className="nav-link">
                  Create Student
                </Link>
              </li>
              <li className="nav-item">
                <Link to={"/student-list"} className="nav-link">
                  Student List
                </Link>
              </li>
            </ul>
          </div>
        </div>
      </nav>

      <div className="container mt-5">
        <div className="wrapper">
          <Routes>
            <Route exact path="/create-student" element={<CreateStudent />} />
            <Route exact path="/edit-student/:id" element={<EditStudent />} />
            <Route exact path="/student-list" element={<StudentList />} />
          </Routes>
        </div>
      </div>
    </div>
  );
}

export default App;

Build REST API with Node and Express

We will create a folder inside our React school management app or at the root of project directory.

Here in this `backend` directory, we will keep files and folder in regards to database, models, schema, routes and APIs, name this folder backend.

Then, we need to create a separate package.json file for managing the backend of our React CRUD demo app example.

npm init -y

Next, install the given below Node dependencies for MERN stack backend.

npm install mongoose express cors body-parser --legacy-peer-deps
NPM Detail
Express It’s a robust Node.js web application framework that helps in creating powerful REST APIs.
MongoDB It’s a NoSQL document-oriented database for creating a robust web application.
CORS It’s a node.js package helps in enabling Access-Control-Allow-Origin CORS header.
bodyParser This package extracts the entire body portion of an incoming request stream and exposes it on req.body.

Install the nodemon dependency to automate the server restarting process.

npm install nodemon --save-dev --legacy-peer-deps

Define Mongoose Schema

Then, create a mongoDB schema for interacting with mongoDB database.

Create backend/Models folder and Student.js file then add the given code into the file.

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

let studentSchema = new Schema({
  name: {
    type: String
  },
  email: {
    type: String
  },
  rollno: {
    type: Number
  }
}, {
    collection: 'students'
  })

module.exports = mongoose.model('Student', studentSchema)

We declared a name, email and rollno fields along with their respective data types in student Schema.

Create REST API Routes

In this step, we are building routes (REST APIs) for React CRUD CREATE, READ, UPDATE and DELETE app using Express and Node.js.

These routes will help us to manage the data in our React MERN stack student app.

Create backend/routes folder and student.routes.js file then add the given code into the file.

let mongoose = require("mongoose"),
  express = require("express"),
  router = express.Router();

// Student Model
let studentSchema = require("../models/Student");

// CREATE Student
router.route("/create-student").post(async (req, res, next) => {
  await studentSchema
    .create(req.body)
    .then((result) => {
      res.json({
        data: result,
        message: "Data successfully added!",
        status: 200,
      });
    })
    .catch((err) => {
      return next(err);
    });
});

// READ Students
router.route("/").get(async (req, res, next) => {
  await studentSchema
    .find()
    .then((result) => {
      res.json({
        data: result,
        message: "All items successfully fetched.",
        status: 200,
      });
    })
    .catch((err) => {
      return next(err);
    });
});

// Get Single Student
router.route("/get-student/:id").get(async (req, res, next) => {
  await studentSchema
    .findById(req.params.id)
    .then((result) => {
      res.json({
        data: result,
        message: "Data successfully fetched.",
        status: 200,
      });
    })
    .catch((err) => {
      return next(err);
    });
});

// Update Student
router.route("/update-student/:id").put(async (req, res, next) => {
  await studentSchema
    .findByIdAndUpdate(req.params.id, {
      $set: req.body,
    })
    .then((result) => {
      console.log(result);
      res.json({
        data: result,
        msg: "Data successfully updated.",
      });
    })
    .catch((err) => {
      console.log(err);
    });
});

// Delete Student
router.route("/delete-student/:id").delete(async (req, res, next) => {
  await studentSchema
    .findByIdAndRemove(req.params.id)
    .then(() => {
      res.json({
        msg: "Data successfully updated.",
      });
    })
    .catch((err) => {
      console.log(err);
    });
});

module.exports = router;

Configure Server File

We have almost created everything to set up the Node and Express.js backend for React MERN Stack CRUD app. Now we will create the index.js file in the root of the backend folder.

At the root of the backend folder to you have to create index.js file.

Paste the following code inside the backend/index.js file.

let express = require("express");
let mongoose = require("mongoose");
let cors = require("cors");
let bodyParser = require("body-parser");

// Express Route
const studentRoute = require("./routes/student.routes");

// Connecting mongoDB Database
mongoose
  .connect("mongodb://127.0.0.1:27017/test")
  .then((x) => {
    console.log(
      `Connected to Mongo! Database name: "${x.connections[0].name}"`,
    );
  })
  .catch((err) => {
    console.error("Error connecting to mongo", err.reason);
  });

const app = express();
app.use(bodyParser.json());
app.use(
  bodyParser.urlencoded({
    extended: true,
  }),
);
app.use(cors());
app.use("/students", studentRoute);

// PORT
const port = process.env.PORT || 4000;
const server = app.listen(port, () => {
  console.log("Connected to port " + port);
});

// 404 Error
app.use((req, res, next) => {
  next(createError(404));
});

app.use(function (err, req, res, next) {
  console.error(err.message);
  if (!err.statusCode) err.statusCode = 500;
  res.status(err.statusCode).send(err.message);
});

To start the node and express server, you must have MongoDB installed on your local development system.

Check out how to install MongoDB community edition on your local machine.

Once the MongoDB community edition has been set up, make sure to start the MongoDB on your local machine then follow the subsequent step.

Next, open the terminal and execute the following command to invoke the MongoDB web server. It will allow you to save the student data in the database.

npx nodemon server

Now, we have created the backend for our MERN stack app.

Following will be your APIs routes created with Express.js, MongoDB and Node.js.

REST API URL
GET http://localhost:4000/students
POST /students/create-student
GET /students/get-student/id
PUT /students/update-student/id
DELETE /students/delete-student/id

You can also test these APIs in Postmen API development tool, click here to download Postmen.

Make CRUD HTTP Requests

In this step, we will learn to use the Axios library in React MERN Stack app to handle the HTTP request. Axios is a promise-based HTTP client for the browser and node.js. It offers the following features.

  • Make XMLHttpRequests from the browser
  • Handle http requests from node.js
  • Supports the Promise API
  • Intercept request and response
  • Transform request and response data
  • Cancel requests
  • Self-regulating for JSON data
  • Client-side protection from XSRF

Run command in the terminal to install axios in React CRUD app.

npm install axios --legacy-peer-deps

Next, we will send the student’s data to the MongoDB server as an object using the Axios post http method.

Add the following code in src/components/CreateStudent.js file:

import React, { useEffect, useState } from "react";
import axios from "axios";

function CreateStudent() {
  const [userForm, setUserForm] = useState({
    name: "",
    email: "",
    rollno: "",
  });

  const inputsHandler = (e) => {
    setUserForm((prevNext) => ({
      ...prevNext,
      [e.target.name]: e.target.value,
    }));
  };

  const onSubmit = (e) => {
    e.preventDefault();
    axios
      .post("http://localhost:4000/students/create-student", userForm)
      .then((res) => {
        console.log(res.data);
        setUserForm({
          name: "",
          email: "",
          rollno: "",
        });
      });
  };

  useEffect(() => {}, []);

  return (
    <div>
      <div className="form-wrapper">
        <form onSubmit={onSubmit}>
          <div className="mb-3">
            <label className="form-label">Name</label>
            <input
              type="text"
              className="form-control"
              name="name"
              id="name"
              value={userForm.name}
              onChange={inputsHandler}
            />
          </div>
          <div className="mb-3">
            <label className="form-label">Email</label>
            <input
              type="text"
              className="form-control"
              name="email"
              id="email"
              value={userForm.email}
              onChange={inputsHandler}
            />
          </div>
          <div className="mb-3">
            <label className="form-label">Roll no.</label>
            <input
              type="text"
              className="form-control"
              name="rollno"
              id="rollno"
              value={userForm.rollno}
              onChange={inputsHandler}
            />
          </div>
          <div className="mb-3">
            <button type="submit" className="btn btn-primary">
              Submit
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

export default CreateStudent;

Then enter the student name, email and rollno and click on Create Student button and your data will be saved in MongoDB NoSQL database.

React MERN Stack CRUD App

Show Data List with React Axios

In this step, we will show the student’s data list using React Axios and react bootstrap. Add the given below code inside the src/components/StudentList.js.

import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import axios from "axios";

function StudentList() {
  const [userForm, setUserForm] = useState([]);

  const deleteStudent = (_id) => {
    axios
      .delete("http://localhost:4000/students/delete-student/" + _id)
      .then(() => {
        console.log("Data successfully deleted!");
      })
      .catch((error) => {
        console.log(error);
      });
  };

  useEffect(() => {
    axios
      .get("http://localhost:4000/students/")
      .then((res) => {
        setUserForm(res.data.data);
      })
      .catch((error) => {
        console.log(error);
      });
  }, [userForm]);

  return (
    <div>
      <table className="table">
        <thead>
          <tr>
            <th scope="col">#</th>
            <th scope="col">Name</th>
            <th scope="col">Email</th>
            <th scope="col">Roll no</th>
            <th scope="col">Action</th>
          </tr>
        </thead>
        <tbody>
          {userForm.map((user, index) => {
            return (
              <tr key={index}>
                <th scope="row">{user._id}</th>
                <td>{user.name}</td>
                <td>{user.email}</td>
                <td>@{user.rollno}</td>
                <td>
                  <Link
                    className="btn btn-primary btn-sm me-2"
                    to={"/edit-student/" + user._id}
                  >
                    Edit
                  </Link>
                  <button
                    className="btn btn-danger btn-sm"
                    onClick={() => deleteStudent(user._id)}
                  >
                    Delete
                  </button>
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

export default StudentList;

In the above code, we are making HTTP GET request using React Axios and Node/Express JS REST API.

Edit, Update and Delete Data in React

In this step, we will create edit and update functionality for the user to manage the student data in React v18.

We used the Axios library and making the PUT request to update the data in MongoDB database using REST API built with Node and Express JS.

Include the given below code inside the EditStudent.js file.

import React, { useEffect, useState } from "react";
import { useParams, useNavigate } from "react-router-dom";

import axios from "axios";

function EditStudent() {
  const [userForm, setUserForm] = useState({
    name: "",
    email: "",
    rollno: "",
  });

  let params = useParams();
  let navigate = useNavigate();

  const inputsHandler = (e) => {
    setUserForm((prevNext) => ({
      ...prevNext,
      [e.target.name]: e.target.value,
    }));
  };

  const onUpdate = (e) => {
    e.preventDefault();
    axios
      .put("http://localhost:4000/students/update-student/" + params.id, {
        name: userForm.name,
        email: userForm.email,
        rollno: userForm.rollno,
      })
      .then((res) => {
        console.log({ status: res.status });
        navigate("/student-list");
      });
  };

  useEffect(() => {
    axios
      .get("http://localhost:4000/students/get-student/" + params.id)
      .then((res) => {
        setUserForm({
          name: res.data.data.name,
          email: res.data.data.email,
          rollno: res.data.data.rollno,
        });
      });
  }, []);

  return (
    <div>
      <div className="form-wrapper">
        <form onSubmit={onUpdate}>
          <div className="mb-3">
            <label className="form-label">Name</label>
            <input
              type="text"
              className="form-control"
              name="name"
              id="name"
              value={userForm.name}
              onChange={inputsHandler}
            />
          </div>
          <div className="mb-3">
            <label className="form-label">Email</label>
            <input
              type="text"
              className="form-control"
              name="email"
              id="email"
              value={userForm.email}
              onChange={inputsHandler}
            />
          </div>
          <div className="mb-3">
            <label className="form-label">Roll no.</label>
            <input
              type="text"
              className="form-control"
              name="rollno"
              id="rollno"
              value={userForm.rollno}
              onChange={inputsHandler}
            />
          </div>
          <div className="mb-3">
            <button type="submit" className="btn btn-primary">
              Update
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

export default EditStudent;

Test App on Browser

To start the React MERN Stack project, run following command:

npm start

This command opens the React project on the following URL: localhost:3000

Download Project Code

You can download full project code from: GitHub

Conclusion

A full-stack MERN (MongoDB, Express, React, and Node.js) CRUD app is a satisfying journey that teaches developers skills that are very useful for making dynamic and useful web apps.

By learning about Create, Read, Update, and Delete (CRUD), developers gain a better understanding of how to effectively handle data in an application’s database.

In the end, making a full-stack MERN CRUD app isn’t just about putting together code; it’s also about making solutions that focus on the user and offer smooth web experiences.

Digamber - Author positronX.io

Hi, I'm Digamber Singh, a New Delhi-based full-stack developer, tech author, and open-source contributor with 10+ years' experience in HTML, CSS, JavaScript, PHP, and WordPress.