I have coded the MERN Stack Tutorial. It is basic CRUD application in which React.js consumes frontend, Node.js as a server platform, Express web framework of Node.js and MongoDB as NoSQL database.

React.js is very famous UI library provided by Facebook. We are using Express web framework, which provides us Routing functionality to our application as well as Middlewares through which we can filter our HTTP requests.

The basic requirement for taking this course

MERN Stack Tutorial

First, we need to build front-end using React.js, set up routing, and create a basic form.

After that, we build backend using the express framework.

Step 1: Draft ReactJS Application.

For set up react application at the front end, we use create-react-app starter kit to initialize our application, so go to the terminal and if you are Windows user, please open CMD in Administrator mode and type following.

npm install -g create-react-app

If you are MAC or Linux user, please type the following command.

sudo npm install -g create-react-app

Go to your project directory and type following command

create-react-app react-frontend

I have given our project’s name react-frontend, you can give whatever you want. It will take some time to initialize our app, and it also installs project dependencies.

After that go into the project folder in my case, it is react-frontend. Type following command.

npm start

At http://localhost:3000/

The development server is started, and basic boilerplate will show in the browser.

Step 2: Install React and ReactDOM.

Now, we need to set up the react-router-dom package. It provides us client-side routing for our web application. So download this package via npm

npm install --save react-router-dom

Note: I am using React Router version 4.1.1, which is new from the previous version of routing package and it is based on components.

I am providing you my package.json file, so you do not worry about it, and if you have any problem, then please check out your all the dependency version with mine.

{ "name": "react-frontend", "version": "0.1.0", "private": true, "dependencies": { "react": "^15.6.1", "react-dom": "^15.6.1", "react-router-dom": "^4.1.1", "react-scripts": "0.9.5" }, "devDependencies": {}, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" } }

Now define your routes in an index.js file, which is in the src directory.

// index.js import React from 'react'; import ReactDOM from 'react-dom'; import { BrowserRouter as Router, Route } from 'react-router-dom'; import App from './App'; ReactDOM.render( <Router> <div> <Route exact path='/' component={App} /> </div> </Router>, document.getElementById('root') );

I am using an ES6 version of JavaScript, so I am importing all of the modules from downloaded packages. Here I am rendering routes as components. Till now, I have defined only one route, which is our app route.

Step 3: Make components folder.

Create one directory in src called components.

In that create one component called AddItem.js

// AddItem.js import React, { Component } from 'react'; class AddItem extends Component { render() { return ( <div> <h2>Welcome to Add Item</h2> </div> ); } } export default AddItem;

Now, we need to import this component to index.js file and also register a route for this component.

// index.js import React from 'react'; import ReactDOM from 'react-dom'; import { BrowserRouter as Router, Route } from 'react-router-dom'; import App from './App'; import AddItem from './components/AddItem'; ReactDOM.render( <Router> <div> <Route exact path='/' component={App} /> <Route path='/add-item' component={AddItem} /> </div> </Router>, document.getElementById('root') );

Now, go this URL: http://localhost:3000/add-item

You will see like “Welcome to Add Item.”

Now, go this URL: http://localhost:3000

You will see like “Welcome to React.”

Possible Errors:

A <Router> may have only one child element

Possible Solutions:

// index.js <Router> <div> <Route exact path='/' component={App} /> <Route path='/add-item' component={AddItem} /> </div> </Router>

Wrap <div> tag around Route component and It will solve this issue.

Step 4: Create a form.

Add the Bootstrap CSS framework to our application. So copy the CDN from a bootstrap official website and put into the index.html file.

<!-- index.html --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

Now, add the bootstrap classes to our add-item.js page

Possible Errors:

Unknown DOM property class.

Possible Solutions:

Use className property instead of class in React application.

Now, create a form to submit the item to the server.

// AddItem.js import React, { Component } from 'react'; class AddItem extends Component { constructor(props) { super(props); this.state = {value: ''}; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert(this.state.value); event.preventDefault(); } render() { return ( <div className="container"> <form onSubmit={this.handleSubmit}> <label> Add Item: <input type="text" value={this.state.value} onChange={this.handleChange} className="form-control"/> </label><br/> <input type="submit" value="Submit" className="btn btn-primary"/> </form> </div> ); } } export default AddItem;

I have used ES6 class syntax. React is all about state change so, first I have set the state to null, and then when the user starts typing in the text box, the state is changed dynamically.

The user puts whatever value in it and state also changes and set the value according to it.

After the user submits the form, the state value, which is set, sent to the server.

So, now we need to send that value to our Node.js server.

I am using one AJAX request library called Axios, which is only used for AJAX request to the server.

Step 5: Make ItemService.js file.

Create a service file in components folder for Items called ItemService.js and put the following code in it.

// ItemService.js import axios from 'axios'; class ItemService { sendData(data) { axios.post('http://localhost:4200/items/add/post', { item: data }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }); } } export default ItemService;

Here, I am using axios library, so I have sent the post request to the server, which is express node server.

Now we just need to import this file in our AddItem.js file.

// AddItem.js import React, { Component } from 'react'; import ItemService from './ItemService'; class AddItem extends Component { constructor(props) { super(props); this.state = {value: ''}; this.addItemService = new ItemService(); this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { event.preventDefault(); this.addItemService.sendData(this.state.value); this.props.history.push('/'); } render() { return ( <div className="container"> <form onSubmit={this.handleSubmit}> <label> Add Item: <input type="text" value={this.state.value} onChange={this.handleChange} className="form-control"/> </label><br/> <input type="submit" value="Submit" className="btn btn-primary"/> </form> </div> ); } } export default AddItem;

Created the object of ItemService class and call its sendData method. Pass the input value as a parameter and ready to go.

Step 6: Make a nodejs express project.

Now, we need to create a backend for our application, so I am using node.js and express web framework.

Create a project folder and go to that directory and put the following command in your terminal.

npm init

After answering all the data, in your root folder package.json file will be created. This file is a config file for our dependencies, so when we download new packages from Node Package Manager, package.json file will be automatically updated.

Step 7: Install expressjs framework.

Get the Express package from Node Package Manager by typing following command on terminal

npm install --save express

Possible Error Info: npm WARN install Refusing to install express as a dependency of itself

If you find above error during installation, make sure your project name must not contain “express” word.

Step 8: Make app.js file.

Create a file in root called “app.js.” This file is our main server file in which it bootstraps the node server, and also it serves some static files. Put the following code in it.

// app.js var express = require('express'); var app = express(); var port = 4200; app.listen(port, function(){ console.log('hello world'); })

Now go to the terminal, and if you type node app, you will get hello world in a console.

If we do not want to restart the server manually, then we can use one package called nodemon. It is kind of server that reloads every time we change the file.

npm install -g nodemon

Change the package.json file and add the following line in “scripts” object.

"start": "nodemon app.js"

When you type in terminal “npm start,” it will bootstrap the server, and when we change the files, it will automatically restart.

Switch to the chrome and hit: http://localhost:4200 We get “Hello Express” in the browser.

Step 9: Install CORS Middleware.

Create Mongoose database connection and also use CORS middleware to request cross-origin domain. Here we are using CORS middleware to bypass the security.

// app.js var express = require('express'); var app = express(); var mongoose = require('mongoose'); var bodyParser = require('body-parser'); var port = 4200; var cors = require('cors'); // Mongoose connection with mongodb mongoose.Promise = require('bluebird'); mongoose.connect('mongodb://<uname>:<pwd>@ds139322.mlab.com:39322/aufinancex') .then(() => { // if all is ok we will be here console.log('Start'); }) .catch(err => { // if error we will be here console.error('App starting error:', err.stack); process.exit(1); }); // Required application specific custom router module var itemRouter = require('./src/routes/itemRouter'); // Use middlewares to set view engine and post json data to the server app.use(express.static('public')); app.use(cors()); app.use(bodyParser.urlencoded({extended: true})); app.use(bodyParser.json()); app.use('/items', itemRouter); // Start the server app.listen(port, function(){ console.log('Server is running on Port: ',port); });

Step 10: Make routes for our application.

Now, create an itemRouter.js file in the src >> routes directory.

I have coded all the CRUD functionality at the backend so don’t worry about it.

I have used Mongoose model to insert, get, update and delete the data.

// itemRoutes.js var express = require('express'); var app = express(); var itemRouter = express.Router(); // Require Item model in our routes module var Item = require('../models/Item'); // Defined store route itemRouter.route('/add/post').post(function (req, res) { var item = new Item(req.body); item.save() .then(item => { res.json('Item added successfully'); }) .catch(err => { res.status(400).send("unable to save to database"); }); }); // Defined get data(index or listing) route itemRouter.route('/').get(function (req, res) { Item.find(function (err, itms){ if(err){ console.log(err); } else { res.json(itms); } }); }); // Defined edit route itemRouter.route('/edit/:id').get(function (req, res) { var id = req.params.id; Item.findById(id, function (err, item){ res.json(item); }); }); // Defined update route itemRouter.route('/update/:id').post(function (req, res) { Item.findById(req.params.id, function(err, item) { if (!item) return next(new Error('Could not load Document')); else { // do your updates here item.item = req.body.item; item.save().then(item => { res.json('Update complete'); }) .catch(err => { res.status(400).send("unable to update the database"); }); } }); }); // Defined delete | remove | destroy route itemRouter.route('/delete/:id').get(function (req, res) { Item.findByIdAndRemove({_id: req.params.id}, function(err, item){ if(err) res.json(err); else res.json('Successfully removed'); }); }); module.exports = itemRouter;

Step 11: Create mongoose schema.

Create a model for Mongoose Schema. So create a new directory in the src folder called models and then create another file in that called Item.js

// Item.js var mongoose = require('mongoose'); var Schema = mongoose.Schema; // Define collection and schema for Items var Item = new Schema({ item: { type: String }, },{ collection: 'items' }); module.exports = mongoose.model('Item', Item);

Possible Errors:

XMLHttpRequest cannot load http://localhost:4200/items/add/post. Response to a preflight request does not pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost:3000’ is therefore not allowed access.

Possible Solutions:

Use middleware package called ‘cors‘ in express application

npm install --save cors

Include this in app.js file in node.js Express project and add as a middleware

//app.js var cors = require('cors'); app.use(cors());

Now, switch to URL: http://localhost:3000/add-item

You can see one form, put the item name and if your backend database connection is perfectly fine then, you can insert the data into the mongo database, and you can redirect back to your home router.

Step 12: Register the routes at the front end.

Next, we need to register index route, so that we can list the items.

//index.js import React from 'react'; import ReactDOM from 'react-dom'; import { BrowserRouter as Router, Route } from 'react-router-dom'; import App from './App'; import AddItem from './components/AddItem'; import IndexItem from './components/IndexItem'; ReactDOM.render( <Router> <div> <Route exact path='/' component={App} /> <Route path='/add-item' component={AddItem} /> <Route path='/index' component={IndexItem} /> </div> </Router>, document.getElementById('root') );

Create new file in components called IndexItem.js

// IndexItem.js import React, { Component } from 'react'; import ItemService from './ItemService'; import axios from 'axios'; import TableRow from './TableRow'; class IndexItem extends Component { constructor(props) { super(props); this.state = {value: '', items: ''}; this.addItemService = new ItemService(); } componentDidMount(){ axios.get('http://localhost:4200/items') .then(response => { this.setState({ items: response.data }); }) .catch(function (error) { console.log(error); }) } tabRow(){ if(this.state.items instanceof Array){ return this.state.items.map(function(object, i){ return <TableRow obj={object} key={i} />; }) } } render() { return ( <div className="container"> <table className="table table-striped"> <thead> <tr> <td>No.</td> <td>Item</td> </tr> </thead> <tbody> {this.tabRow()} </tbody> </table> </div> ); } } export default IndexItem;

Here, I have sent the axios to get a request to the node.js server, nd in response, we are getting the data.

So we are rendering that data in our ItemIndex.js file and also we are creating one more component, which is only responsible for making the table.

So create one more component called TableRow.js

// TableRow.js import React, { Component } from 'react'; class TableRow extends Component { render() { return ( <tr> <td> {this.props.obj._id} </td> <td> {this.props.obj.item} </td> <td> <button className="btn btn-primary">Edit</button> </td> <td> <button className="btn btn-danger">Delete</button> </td> </tr> ); } } export default TableRow;

So Indexing of data is complete till now.

Now, remaining is editing and deleting.

Step 13: Make editItem.js file.

Create a new edit file in components called “EditItem.js.” Put the following code in it.

// EditItem.js import React, { Component } from 'react'; import axios from 'axios'; class EditItem extends Component { constructor(props) { super(props); this.state = {items: ''}; } componentDidMount(){ axios.get('http://localhost:4200/items/edit/'+this.props.match.params.id) .then(response => { this.setState({ items: response.data }); }) .catch(function (error) { console.log(error); }) } render() { return ( <div className="container"> <form onSubmit={this.handleSubmit}> <label> Edit Item: <input type="text" value={this.state.items.item} className="form-control"/> </label><br/> <input type="submit" value="Update" className="btn btn-primary"/> </form> </div> ); } } export default EditItem;

Here I am fetching exact editable data from the database via their _id

Also, put an edit link in TableRow.js file.

// TableRow.js <Link to={"/edit/"+this.props.obj._id} className="btn btn-primary">Edit</Link>

Register the route in the index.js file.

// Index.js import EditItem from './components/EditItem'; <Route path='/edit/:id' component={EditItem} />

Step 14: Update the data.

Now, updating our data so, we need to change EditItem.js file

// EditItem.js import React, { Component } from 'react'; import axios from 'axios'; import ItemService from './ItemService'; class EditItem extends Component { constructor(props) { super(props); this.addItemService = new ItemService(); this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); this.state = {value: '' }; } componentDidMount(){ axios.get('http://localhost:4200/items/edit/'+this.props.match.params.id) .then(response => { this.setState({ value: response.data}); }) .catch(function (error) { console.log(error); }) } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { event.preventDefault(); this.addItemService.updateData(this.state.value,this.props.match.params.id); this.props.history.push('/index'); } render() { return ( <div className="container"> <form onSubmit={this.handleSubmit}> <label> Edit Item: <input type="text" value={this.state.value.item} onChange={this.handleChange} className="form-control"/> </label><br/> <input type="submit" value="Update" className="btn btn-primary"/> </form> </div> ); } } export default EditItem;

Also, we need to code the update function in ItemService.js file

// ItemService.js updateData(data, id){ axios.post('http://localhost:4200/items/update/'+id, { item: data }) .then(res => this.setState({ items: res.data })) .catch(err => console.log(err)) }

Now when you edit the file and update the data, you will redirect index.js component, and when you refresh the page, data is updated.

Step 15: Delete the data.

Now, we proceed to delete the data.

So we need to modify the TableRow.js file, where we have put the delete button.

// TableRow.js import React, { Component } from 'react'; import {Link} from 'react-router-dom'; import ItemService from './ItemService'; class TableRow extends Component { constructor(props) { super(props); this.addItemService = new ItemService(); this.handleSubmit = this.handleSubmit.bind(this); } handleSubmit(event) { event.preventDefault(); this.addItemService.deleteData(this.props.obj._id); } render() { return ( <tr> <td> {this.props.obj._id} </td> <td> {this.props.obj.item} </td> <td> <Link to={"/edit/"+this.props.obj._id} className="btn btn-primary">Edit</Link> </td> <td> <form onSubmit={this.handleSubmit}> <input type="submit" value="Delete" className="btn btn-danger"/> </form> </td> </tr> ); } } export default TableRow;

Next step is to code ItemService.js file

// ItemService.js deleteData(id){ axios.get('http://localhost:4200/items/delete/'+id) .then(console.log('Deleted').catch(err => console.log(err)) }

Now, when you delete the button and refresh the page, we can see that the item has been removed.

Note: In the React.js project, generally page refresh is not worth it, but I have created this project to just showcase that how we can work with both React.js and Node.js

Github Links

Github Steps To Use MERN Stack Tutorial

Clone The reactfrontend project repo. Go to the project folder run the command “npm install” in your terminal after that, run the command “npm start.” Clone the expressbackend repo. Go to the project folder run the command “npm install” in your terminal In app.js file change MongoDB URI to your particular URI run the command “npm start“ Now, go this URL: http://localhost:3000/add-item

If you still have any doubt in MERN Stack Tutorial then ask in a comment below I am happy to help you out.