Search

React CRUD Example using MongoDB | Express | React | NodeJs

post-title

Today, I am going to teach you how to build React CRUD web application from scratch. Along with that, we will learn how to set up a Node server and create REST APIs using Node and Express.js.

React MERN Stack Example

In this MERN stack tutorial, we will create a basic Student app from starting to finish. This app will allow us to create student, show students list, update student, and delete a student from the MongoDB database.

Before we move further let’s understand

What is MERN stack?

MERN Stack stands for MongoDB, Express, React, Node.js and this combined stack is known as MERN stack.

Stack Detail
MongoDB A document-oriented database programme based on NoSQL.
Express It’s a robust Node.js web application framework that helps in creating powerful REST APIs.
React A JavaScript library used to create beautiful and interactive user interfaces developed by Facebook and the community of individual developers.
Node

It’s a JavaScript runtime environment built on Google Chrome’s V8 engine, and it compiles js at the runtime.

Tutorial Objective

  • Setting up React project
  • Creating components in React
  • Building and working with React routers
  • Working with React-Bootstrap
  • Getting started with React forms
  • Consuming REST APIs in React app
  • Getting started with Create, Read, Update and Delete in React
  • Setting up a Node and Express server
  • MongoDB set up in MERN stack project
  • Creating REST APIs using Express.js
  • Making HTTP requests with React Axios library

Prerequisites

Before getting started with this tutorial, you must be aware of the fundamentals of React.js and HTML, CSS, JavaScript, TypeScript, or ES6. Check out React’s official website to know more about its features, central concepts, and API reference here.

In order to build MERN Stack web application, you must have Node.js installed on your system. Ignore this step if Node is already installed otherwise follow this step by step written article on how to install Node.js?

Once the Node is installed run below cmd to check the Node.js version:

node -v
# v10.16.0

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

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

npm start

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

Once the React is installed successfully, then you can verify the React version in package.json file.

"dependencies": {
    "react": "^16.9.0",
    "react-dom": "^16.9.0",
  }

Now, you are all set to build the React CRUD app!

Integrating React Bootstrap with React App

In the next step, we will install the React Bootstrap front-end framework in our MERN stack app. This framework will allow us to use the Bootstrap’s UI component in our React CRUD app.

React Bootstrap allows us to import individual UI components instead of importing the whole set of libraries.

npm install react-bootstrap bootstrap

Then, go to src/app.js and import the following Bootstrap CSS above App.css file.

import 'bootstrap/dist/css/bootstrap.css';

You can add <link> tag in your React app’s index.html file to use the Bootstrap UI components. You can also import individual Bootstrap 4 components in your React CRUD app.

Creating Simple React Components

In this step, we will learn to create react components for managing data in the MERN stack CRUD application.

Head over to src folder, make a folder and name it components and within that directory create the following components.

  • create-student.component.js
  • edit-student.component.js
  • student-list.component.js

Go to src/components/create-student.component.js and add the following code.

import React, { Component } from "react";

export default class CreateStudent extends Component {
  render() {
    return (
      <div>
        <p>React Create Student Component!</p>
      </div>
    );
  }
}

Go to src/components/edit-student.component.js and add the following code.

import React, { Component } from "react";

export default class EditStudent extends Component {
  render() {
    return (
      <div>
        <p>React Edit Student Component!</p>
      </div>
    );
  }
}

Go to src/components/student-list.component.js and add the following code.

import React, { Component } from "react";

export default class StudentList extends Component {
  render() {
    return (
      <div>
        <p>React Student List Component!</p>
      </div>
    );
  }
}

Implementing React Router

In this step, we will implement router in React.js app. Enter the command in terminal and hit enter to install the React Router.

npm install react-router-dom --save

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";
import { BrowserRouter } from "react-router-dom";

import "./index.css";
import App from "./App";
import * as serviceWorker from "./serviceWorker";

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

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

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

import React from "react";
import Nav from "react-bootstrap/Nav";
import Navbar from "react-bootstrap/Navbar";
import Container from "react-bootstrap/Container";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
import "bootstrap/dist/css/bootstrap.css";
import "./App.css";

import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";

import CreateStudent from "./components/create-student.component";
import EditStudent from "./components/edit-student.component";
import StudentList from "./components/student-list.component";

function App() {
  return (<Router>
    <div className="App">
      <header className="App-header">
        <Navbar bg="dark" variant="dark">
          <Container>

            <Navbar.Brand>
              <Link to={"/create-student"} className="nav-link">
                React MERN Stack App
              </Link>
            </Navbar.Brand>

            <Nav className="justify-content-end">
              <Nav>
                <Link to={"/create-student"} className="nav-link">
                  Create Student
                </Link>
              </Nav>

              {/* <Nav>
                <Link to={"/edit-student/:id"} className="nav-link">
                  Edit Student
                </Link>
              </Nav> */}

              <Nav>
                <Link to={"/student-list"} className="nav-link">
                  Student List
                </Link>
              </Nav>
            </Nav>

          </Container>
        </Navbar>
      </header>

      <Container>
        <Row>
          <Col md={12}>
            <div className="wrapper">
              <Switch>
                <Route exact path='/' component={CreateStudent} />
                <Route path="/create-student" component={CreateStudent} />
                <Route path="/edit-student/:id" component={EditStudent} />
                <Route path="/student-list" component={StudentList} />
              </Switch>
            </div>
          </Col>
        </Row>
      </Container>
    </div>
  </Router>);
}

export default App;

Create React Form with React Bootstrap

In this step, we will build the form using React Bootstrap front-end framework for submitting the Student data in the create-student.component.js component.

import React, {Component} from "react";
import Form from 'react-bootstrap/Form'
import Button from 'react-bootstrap/Button';

export default class CreateStudent extends Component {
  render() {
    return (<div class="form-wrapper">
      <Form>
        <Form.Group controlId="Name">
          <Form.Label>Name</Form.Label>
          <Form.Control type="text"/>
        </Form.Group>

        <Form.Group controlId="Email">
          <Form.Label>Email</Form.Label>
          <Form.Control type="email"/>
        </Form.Group>

        <Form.Group controlId="Name">
          <Form.Label>Roll No</Form.Label>
          <Form.Control type="text"/>
        </Form.Group>

        <Button variant="danger" size="lg" block="block" type="submit">
          Create Student
        </Button>
      </Form>
    </div>);
  }
}

Submit Forms Data in React

Next, we will learn to submit the Forms data in React.js. We have already created the Student form, and need to submit student’s: Name, Email and Roll No to the database.

We will start by creating the constructor inside the CreateStudent component class. Then set the initial state of the CreateStudent component by setting this.state Object.

Then declare the various functions with every React form field value, so when the user inserts the data within the form input field, a state will be set accordingly.

Next, we need to define the submit event, which will allow us to create new student data when the user clicks on `Create Student` submit button.

import React, {Component} from "react";
import Form from 'react-bootstrap/Form'
import Button from 'react-bootstrap/Button';

export default class CreateStudent extends Component {

  constructor(props) {
    super(props)

    // Setting up functions
    this.onChangeStudentName = this.onChangeStudentName.bind(this);
    this.onChangeStudentEmail = this.onChangeStudentEmail.bind(this);
    this.onChangeStudentRollno = this.onChangeStudentRollno.bind(this);
    this.onSubmit = this.onSubmit.bind(this);

    // Setting up state
    this.state = {
      name: '',
      email: '',
      rollno: ''
    }
  }

  onChangeStudentName(e) {
    this.setState({name: e.target.value})
  }

  onChangeStudentEmail(e) {
    this.setState({email: e.target.value})
  }

  onChangeStudentRollno(e) {
    this.setState({rollno: e.target.value})
  }

  onSubmit(e) {
    e.preventDefault()

    console.log(`Student successfully created!`);
    console.log(`Name: ${this.state.name}`);
    console.log(`Email: ${this.state.email}`);
    console.log(`Roll no: ${this.state.rollno}`);

    this.setState({name: '', email: '', rollno: ''})
  }

  render() {
    return (<div className="form-wrapper">
      <Form onSubmit={this.onSubmit}>
        <Form.Group controlId="Name">
          <Form.Label>Name</Form.Label>
          <Form.Control type="text" value={this.state.name} onChange={this.onChangeStudentName}/>
        </Form.Group>

        <Form.Group controlId="Email">
          <Form.Label>Email</Form.Label>
          <Form.Control type="email" value={this.state.email} onChange={this.onChangeStudentEmail}/>
        </Form.Group>

        <Form.Group controlId="Name">
          <Form.Label>Roll No</Form.Label>
          <Form.Control type="text" value={this.state.rollno} onChange={this.onChangeStudentRollno}/>
        </Form.Group>

        <Button variant="danger" size="lg" block="block" type="submit">
          Create Student
        </Button>
      </Form>
    </div>);
  }
}

Build Node JS Backend for MERN Stack

We will create a folder inside our React app to manage the `backend` services such as database, models, schema, routes and APIs, name this folder backend.

Run command to create backend folder and get inside of it.

mkdir backend && cd backend

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

npm init

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

npm install mongoose express cors body-parser
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

Your final package.json file will look something like this.

{
  "name": "mearn-stack-backend",
  "version": "1.0.0",
  "description": "MERN Stack backend",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Digamber Rawat",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.19.0",
    "cors": "^2.8.5",
    "express": "^4.17.1",
    "mongoose": "^5.6.9"
  },
  "devDependencies": {
    "nodemon": "^1.19.1"
  }
}

Setting up MongoDB Database

Next, we will set up a MongoDB database for React MERN stack app. We have already installed mongoDB, create database folder inside the backend folder and create a file by the name of db.js and paste the following code inside of it.

module.exports = {
  db: 'mongodb://localhost:27017/reactdb'
};

We have declared the mongoDB database, here 'reactdb' is the database name. Locally it doesn’t require user name and password; however, in the production, you must create an admin and assign the database to a specific user.

Define Mongoose Schema

Then, create a mongoDB schema for interacting with mongoDB database. Create a folder inside backend folder to keep schema related files and name it Models and create a file Student.js inside of it.

mkdir Models && cd Models && touch Student.js

Next, include the following code in backend/models/Student.js 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 Routes Using Express/Node JS for React CRUD App

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 a folder and name it routes, here we will keep all the routes related files. Also, create the student.routes.js file inside this folder in this file we will define REST APIs.

mkdir routes && cd routes && touch student.route.js

Then, go to backend/routes/student.route.js file and add the following code.

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

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

// CREATE Student
router.route('/create-student').post((req, res, next) => {
  studentSchema.create(req.body, (error, data) => {
    if (error) {
      return next(error)
    } else {
      console.log(data)
      res.json(data)
    }
  })
});

// READ Students
router.route('/').get((req, res) => {
  studentSchema.find((error, data) => {
    if (error) {
      return next(error)
    } else {
      res.json(data)
    }
  })
})

// Get Single Student
router.route('/edit-student/:id').get((req, res) => {
  studentSchema.findById(req.params.id, (error, data) => {
    if (error) {
      return next(error)
    } else {
      res.json(data)
    }
  })
})


// Update Student
router.route('/update-student/:id').put((req, res, next) => {
  studentSchema.findByIdAndUpdate(req.params.id, {
    $set: req.body
  }, (error, data) => {
    if (error) {
      return next(error);
      console.log(error)
    } else {
      res.json(data)
      console.log('Student updated successfully !')
    }
  })
})

// Delete Student
router.route('/delete-student/:id').delete((req, res, next) => {
  studentSchema.findByIdAndRemove(req.params.id, (error, data) => {
    if (error) {
      return next(error);
    } else {
      res.status(200).json({
        msg: data
      })
    }
  })
})

module.exports = router;

Configure Server.js in Node/Express.js Backend

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

Run command from the root of the backend folder to create server.js file.

touch server.js

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

let express = require('express');
let mongoose = require('mongoose');
let cors = require('cors');
let bodyParser = require('body-parser');
let dbConfig = require('./database/db');

// Express Route
const studentRoute = require('../backend/routes/student.route')

// Connecting mongoDB Database
mongoose.Promise = global.Promise;
mongoose.connect(dbConfig.db, {
  useNewUrlParser: true
}).then(() => {
  console.log('Database sucessfully connected!')
},
  error => {
    console.log('Could not connect to database : ' + error)
  }
)

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);
});

Now, we have created the backend for our MERN stack app. Open the terminal and run the command to start MongoDB, It will allow you to save the student data in the database.

mongod

Also, open another terminal and run the following command to start the Nodemon server by staying in the backend folder.

nodemon server.js

# [nodemon] 1.19.1
# [nodemon] to restart at any time, enter `rs`
# [nodemon] watching: *.*
# [nodemon] starting `node server.js`
# Connected to port 4000
# Database sucessfully connected!

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/edit-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.

Using Axios with React to Make HTTP Request

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

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

import React, { Component } from "react";
import Form from 'react-bootstrap/Form'
import Button from 'react-bootstrap/Button';
import axios from 'axios';

export default class CreateStudent extends Component {

  constructor(props) {
    super(props)

    // Setting up functions
    this.onChangeStudentName = this.onChangeStudentName.bind(this);
    this.onChangeStudentEmail = this.onChangeStudentEmail.bind(this);
    this.onChangeStudentRollno = this.onChangeStudentRollno.bind(this);
    this.onSubmit = this.onSubmit.bind(this);

    // Setting up state
    this.state = {
      name: '',
      email: '',
      rollno: ''
    }
  }

  onChangeStudentName(e) {
    this.setState({ name: e.target.value })
  }

  onChangeStudentEmail(e) {
    this.setState({ email: e.target.value })
  }

  onChangeStudentRollno(e) {
    this.setState({ rollno: e.target.value })
  }

  onSubmit(e) {
    e.preventDefault()

    const studentObject = {
      name: this.state.name,
      email: this.state.email,
      rollno: this.state.rollno
    };
    axios.post('http://localhost:4000/students/create-student', studentObject)
      .then(res => console.log(res.data));

    this.setState({ name: '', email: '', rollno: '' })
  }

  render() {
    return (<div className="form-wrapper">
      <Form onSubmit={this.onSubmit}>
        <Form.Group controlId="Name">
          <Form.Label>Name</Form.Label>
          <Form.Control type="text" value={this.state.name} onChange={this.onChangeStudentName} />
        </Form.Group>

        <Form.Group controlId="Email">
          <Form.Label>Email</Form.Label>
          <Form.Control type="email" value={this.state.email} onChange={this.onChangeStudentEmail} />
        </Form.Group>

        <Form.Group controlId="Name">
          <Form.Label>Roll No</Form.Label>
          <Form.Control type="text" value={this.state.rollno} onChange={this.onChangeStudentRollno} />
        </Form.Group>

        <Button variant="danger" size="lg" block="block" type="submit">
          Create Student
        </Button>
      </Form>
    </div>);
  }
}