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