A MERN stack application consists of four components:
To create a simple full-stack MERN application, we must first set up the development environment.
We must configure and install the components mentioned above on our systems first.
We can install NodeJS on Windows or macOS by downloading the installer from here and running it.
To install NodeJS on Ubuntu, we must follow the steps mentioned here.
To install ReactJS, we must go to the desired folder where we want to create the application and open "cmd" in Windows or "terminal" in Linux/macOS. Then, we run the following command:
npx create-react-app <myapp>
Here, <myapp>
will be replaced by a custom application name.
After a successful execution, this command creates a custom React application with some boilerplate code already available. We can verify the correct installation of our application by executing the following commands:
1. cd <myapp>2. npm start
Our browser loads the boilerplate code and displays the react logo in a tab.
To install ExpressJS, we open the React application directory in "terminal"/"cmd" and run the following command:
npm init
The above command creates a package.json
file in the directory. For default settings, we just hit "RETURN."
After that, we run the following:
npm install express
This step installs Express in our application directory. The index.js
file will have our Express code. We rename the file to Server.js
.
We can install MongoDB in our systems by following the instructions on the official MongoDB website.
After the installation, we need to set up Mongoose, a tool that lets us work in an asynchronous environment.
The following command executes for Mongoose installation in our application:
npm install mongoose
After this command, we can see mongoose
as a dependency in the package.json
file.
react-router-dom
package installationWe need the react-router-dom
package to enable navigation in our application. To install it, we run the following command:
npm install react-router-dom
Axios is an
npm install axios
This adds axios
as a dependency in the package.json
file.
Cors is used to provide express
npm install cors
We will develop a simple 'To-Do List" application as follows:
First, let's start designing HTML pages and the react components we need.
Note: We do not consider styling in this application.
Our application will have two HTML pages. We will use one to add tasks, and the other one to display a to-do list.
Let's start by creating React components and importing them to the HTML pages. To do this, we do as follows:
Create a folder inside the application's frontend
directory and place all other files/folders inside this one. Delete the public
folder and create a directory called components
inside the src
folder.
Add a .js
file named TaskComponent
in the components
directory. It will represent a to-do task.
Design the TaskComponent
using the functional React component.
Create another folder named pages
inside the src
folder. It will contain our HTML pages.
Add two files named addTask.js
and ToDoList.js
inside the newly created folder.
Design the addTask.js
page.
Import the React component for the ToDoList.js
page and design it.
Delete all the other files that we do not need.
Our application currently looks like this:
i=0 cd /backend/src && node Server.js & while : do curl {{EDUCATIVE_LIVE_VM_URL}}:3000/Tasks/getTasks >& log.txt; if grep "Your app refused to connect." < log.txt > waste.txt; then i=0 else break; fi done
In the component
file:
Line 2: We use the react
functional component to implement the task
component. Inside that functional component, we design it and send props
as the parameter.
Lines 10, 13: The props parameter contains the id
and task
(details) that we show on the page.
On the ToDoList.js
page:
Lines 1–2: We import useEffect
and axios
as we want to display all the tasks on the first-page load.
Lines 6, 20: We import and return the task component in a map()
function. This map()
function runs the task component for all the tasks available in the database.
Lines 10–16: We use axios.get()
to fetch data from the route passed in as the parameter and, in response, we set the task state as the list of tasks that is the return value of the axios.get()
fetch request.
Line 14: The prop passed in as the parameter has the setTasks()
method that will be used to update the list of tasks.
Line 26: Finally, we have a button
that redirects us to the "add task" page (home page).
On the AddTask.js
page:
Lines 7–29: It has a useState
that tracks what the user inputs to the input field, and an event handler that adds the task details to the database using axios.post()
. In the handleClick()
event handler function, we create a new object based on the details input by the user. We use the POST request to send this object and save it in the database.
Lines 33–46: There is one input field that has the task description and two buttons named submit task
and view list
. We use them to add a task to the database and re-route to the ToDoList.js
page.
In the app.js
file:
Line 8: We have our primary state of tasks as it comes at the top in the file hierarchy.
Lines 10–17: Secondly, we have react-router
routes
that navigates to particular pages when a specific URL hit occurs. The tasks
state is passed to the pages as props, along with its setter function, so that the state can be updated globally at any point of our application.
After implementing the frontend, let's focus on how to design and code the backend of our project. For this, we do the following:
Create a folder named backend
in the application directory. Inside that folder, create a directory called src
.
Add two new folders in the src
directory named routes
and schema
.
This folder contains all of the
Add a .js
file called tasks.js
inside this folder.
Import express
and run its router
.
Create GET
and POST
APIs and assign URL routes to these APIs.
These APIs are responsible for the data flow between the user and the database.
Export the router
as a module.
//creating express routerconst express = require('express')var router = express.Router()//importing task model from taskSchema.jsconst taskTable = require('../schema/taskSchema')//api for fetching all tasks from dbrouter.get('/getTasks',function(req,res){taskTable.find({},(err,tasks)=>{if(err)res.send(err)elseres.send(tasks)})})//api to add task to dbrouter.post('/addTask',async(req,res)=>{const recv_id = req.body.idconst recv_details = req.body.detailsvar newTask = new taskTable({id:recv_id,details:recv_details})newTask.save((err,doc)=>{if(err)res.send("Cannot add task!")elseres.send("Task added!")})})module.exports=router;
There are two routes in this file.
Lines 7–14: One route handles the GET request when the /getTasks
URL hit occurs. In the GET request handler route, the find()
query fetches all the tasks in the taskTable
. If there is no error, the tasks are returned as a response.
Lines 16–29: The other handles the POST request when the /addTask
URL hit occurs. We also import the taskTable
to communicate with the database. In the POST request handler route, we create a new taskTable
object based on the parameters received by the handler. We use the save()
function to store the details in the database.
schema
folderThe schema
folder has code that implements the database table for our tasks. Let's see the steps that we need to execute:
Add a file named taskSchema.js
in the schema
folder.
Import mongoose
.
Create a new schema using the mongoose.Schema()
function, which takes fields as parameters.
Create a table using the mongoose.model()
function that has two parameters. The first is the title assigned to the task table, and the second is the schema we just created.
Export the model as a module.
const mongoose = require('mongoose')//schema with two fieldsconst taskSchema = new mongoose.Schema({id:Number,details:String})const taskTable = new mongoose.model('Tasks',taskSchema)module.exports = taskTable;
Lines 3–6: We declare the taskSchema
variable as a schema with the mongoose.Schema()
function, where id
and details
are fields of this schema.
Line 7: The taskTable
variable represents a table of the schema mentioned above, and we define it using the mongoose.model()
function with the title being Tasks
.
Server.js
fileWe add the Server.js
file in the backend directory. This file is responsible for handling our nodeJS server.
To create this file, we do as follows:
Import express
and run the express()
function for a variable.
Acquire cors
.
The use()
function of express
utilizes all the resources needed to make our application work. This includes schemas, routes, and packages.
Establish a connection with the database using the mongoose.connect()
function and giving its parameters.
Use our application routes.
The listen()
function runs the server on the port we pass as the parameter.
//important importsconst express = require('express')const app= express()const cors = require('cors')//for parsingapp.use(express.json())app.use(express.urlencoded({ extended: true }))app.use(cors())//database connectionconst mongoose = require('mongoose')mongoose.connect('mongodb://localhost:27017/ToDOList',{useNewUrlParser:true,useUnifiedTopology:true});//using the apisconst taskRouter = require('./routes/tasks')app.use('/Tasks',taskRouter);//listening to port 3000app.listen(3000,()=>{console.log("Server is running on port: 3000")})
Lines 11–14: After the required imports, we connect to the database on port 27017
. The name of our database is ToDOList
.
Lines 16–21: Then, we make express use of our NodeJS routes by passing the taskRouter
variable to the express variable named app
and listening to the port 3000
.
The following widget represents our working application. Let's hit the "Run" button to see how our application works:
i=0 cd /backend/src && node Server.js & while : do curl {{EDUCATIVE_LIVE_VM_URL}}:3000/Tasks/getTasks >& log.txt; if grep "Your app refused to connect." < log.txt > waste.txt; then i=0 else break; fi done
Note: The application might take some time to load on the website.
We need two terminals to run the project on your machine. For this, we must follow the below steps:
cd
to the backend
folder and run this command: node Server.js
. It will run the backend server.
cd
to the frontend
folder and run this command: npm start
. The React server will run, and the application will be loaded on a browser tab.
Free Resources