Code  JS

Code JS

1669344959

Build a Complete Fullstack Responsive MERN App

Build a COMPLETE Fullstack Responsive MERN App with Auth, Likes, Dark Mode | React, MongoDB, MUI

Chapters:
0:00 Build a Fullstack MERN React Responsive Social Media Application from Scratch
5:07 Backend Installation of Node, Visual Studio Code, and Backend Packages
7:44 Backend Configurations and Middleware Setup
16:06 MongoDB Registering, Installation and Setup
21:31 Data Modeling and ERD Diagrams
26:08 Authentication and Authorization in Node
59:07 User Routes Setup
1:13:33 Post Routes Setup
1:36:20 Backend Data Add and Demo
1:42:20 Frontend Installation and Setup
1:48:34 React Redux File Folder Architecture and React Router
1:56:10 Redux and Toolkit Installation and Setup
2:10:56 Color, Theme, Dark Mode, and Styling Setup
2:26:16 Navbar
2:48:37 Register, Login Pages, and Form
3:34:44 Home Page and Widgets
4:04:17 Posts and Post Widgets
5:19:41 Profile Page
5:27:08 Full Stack MERN React Application Complete

Links:
Material UI: https://mui.com/material-ui/getting-started/installation/ 
Redux Toolkit: https://redux-toolkit.js.org/introduction/getting-started 
React Router: https://reactrouter.com/en/v6.3.0/getting-started/installation 
Redux Persist: https://github.com/rt2zz/redux-persist 
React Dropzone: https://react-dropzone.js.org/ 
Node: https://nodejs.org/en/download/ 
Nodemon: https://github.com/remy/nodemon 
NPX: https://www.npmjs.com/package/npx 
VsCode: https://code.visualstudio.com/download 
Dotenv: https://github.com/motdotla/dotenv 
MongoDB: https://www.mongodb.com/ 
Mongoose: https://github.com/Automattic/mongoose 
JsonWebToken: https://github.com/auth0/node-jsonwebtoken 
Multer: https://github.com/expressjs/multer 
GridFS-Storage: https://github.com/devconcept/multer-gridfs-storage 
Google Fonts: https://fonts.google.com/ 
Formik: https://formik.org/docs/overview 
Yup: https://github.com/jquense/yup 

Code
completed code: https://github.com/ed-roh/mern-social-media 
assets file: https://github.com/ed-roh/mern-social-media/tree/master/server/public/assets 
input data file: https://github.com/ed-roh/mern-social-media/blob/master/server/data/index.js 
theme file: https://github.com/ed-roh/mern-social-media/blob/master/client/src/theme.js 

Subscribe: https://www.youtube.com/channel/UCMoEx7gz7IbJHv733yEi2aA/?sub_confirmation=1 
 

#javascript #mern #node #react 

Build a Complete Fullstack Responsive MERN App
Code  JS

Code JS

1668484601

MERN Stack Inventory Management App | Advanced MERN Tutorial

Learn the MERN stack - MongoDB Express React NodeJS

-------- Pinvent App - Timeline ---------
00:00:00 - Promo Intro
00:01:37 - Pinvent App Demo
00:18:58 - Planning the Project
00:23:18 - Project Setup
00:29:34 - Create Server and Connect MongoDB
00:43:50 - Create Folders and Home Route
00:55:54 - Create User Model
01:11:08 - Create User Route
01:16:34 - Create User Controller
01:21:37 - Create Custom Error Handler
01:34:48 - Register New User
01:54:25 - Encrypt Password - Method 1
02:03:53 - Encrypt Password - Method 2
02:13:04 - Generate JSON Web Token
02:23:46 - Send Token With HTTP-Only cookie
02:34:26 - Create Login Route
02:38:15 - Create Login Controller Function
02:50:58 - Logout User
02:57:33 - Create User Profile Route
03:03:07 - Create Protect MiddleWare and UserProfile Controller
03:16:16 - Create Route to Get Login Status
03:20:26 - Create  Login Status Controller Function
03:23:41 - Create  Route to Update User
03:28:23 - Create  Update User Controller Function
03:39:24 - Create  Route to Change Password
03:43:06 - Create  Controller Function to Change Password
03:52:06 - Reset Password Process
03:56:55 - Create Forgot Password Route
04:00:48 - Create Token Model
04:06:52 - Create send Email Function
04:22:10 - Forgot Password Controller Function - Part 1
04:33:39 - Forgot Password Controller Function - Part 2
04:44:07 - Forgot Password Controller Function - Part 3
04:59:08 - Email not delivered
05:01:59 - Create Reset Password Route
05:05:52 - Create Reset Password Controller

Subscribe: https://www.youtube.com/c/ZinoTrustAcademy/featured 

#javascript #mern #react #nodejs #mongodb #express 

MERN Stack Inventory Management App | Advanced MERN Tutorial

Deploy MERN ECommerce On Ubuntu Using Hostinger VPS

In this tutorial, you'll learn how to deploy MERN (MongoDB, Express, React, and NodeJS) E-Commerce on Ubuntu using Hostinger VPS

TABLE OF CONTENT
00:00 Introduction
00:01:44 Buy VPS Server
00:03:05 Configure VPS Server
00:06:26 Buy Domain
00:09:23 Deploy Website
00:22:42 Clone Amazona Repo

👉 View Demo  : https://mern-ecommerce-app.com/ 
👉 Source Code: https://github.com/basir/mern-amazona 

#mern #mongodb #express #node #react #ubuntu 

Deploy MERN ECommerce On Ubuntu Using Hostinger VPS

Simple Authentification System with MERN Stack | Password Reset

Simple Authentification System (include password reset) with MERN stack :

MERN APP for registering users with mongodb and authentication using a JWT (json web token), It includes also a password reset functionality.

Configuration :

Create a config.env file in the root directory and fill it with the following informations :

PORT=5000

DATABASE_CONNECTION="Your DB URI"

JWT_SECRET="Your JWT Secret key"
JWT_EXPIRE="10min"

#For password Reset :

EMAIL_SERVICE=""
EMAIL_USERNAME=""
EMAIL_PASSWORD=""
EMAIL_FROM=""

Quick Start :

// Install dependencies for server & client
npm install && npm run client-install

// Run client & server with concurrently
npm run dev

// Server runs on http://localhost:5000 and client on http://localhost:3000

package.json

{
  "name": "password_reset",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": {
    "server": "nodemon server",
    "client": "npm start --prefix client",
    "dev": "concurrently \"npm run server\" \"npm run client\""
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "bcryptjs": "^2.4.3",
    "dotenv": "^8.2.0",
    "express": "^4.17.1",
    "jsonwebtoken": "^8.5.1",
    "mongoose": "^5.11.9",
    "nodemailer": "^6.4.17"
  },
  "devDependencies": {
    "concurrently": "^5.3.0",
    "nodemon": "^2.0.6"
  }
}

Download Details:
 

Author: LloydJanseVanRensburg 
Download Link: Download The Source Code
Official Website: https://github.com/LloydJanseVanRensburg/AdvancedNodeAuth 
 

#nodejs #mern #javascript 

Simple Authentification System with MERN Stack | Password Reset
Code  JS

Code JS

1664938229

Advanced User Authentication & Authorization | Mern Authentication

In this video we will create an advanced application with MERN Stack, It will  be a user authentication and authorization Project With Login And Signup Application In MERN Stack.

Timestamps:
0:00 Introduction and Overview of Tutorial
1:01 Application DEMO
3:09 Introduction to MERN Stack and Project
10:23 Creating Backend - Creating NodeJS Project from Scratch
13:55 Creating Backend - Installing Express in NodeJS
16:43 Creating Backend - Configuring MongoDB
20:10 Creating Backend - Installing and Configuring Mongoose
21:08 Creating Backend - Connecting Application With MongoDB Database
24:04  Creating Backend - Folder Structure
25:05  Creating Backend - Adding User Model
28:19  Creating Backend - Adding Routes
30:59 Creating Backend - Installing Postman
32:10 Creating Backend - Creating Signup Route and Controller
38:47 Creating Backend - Adding Validation To Controllers
43:02 Creating Backend - Encrypting / Hashing Password With Bcryptjs
46:28 Creating Backend - Login Route
53:02 Creating Backend - Adding JWT Token For Authorization
59:34 Creating Backend - Adding Verification Of JWT Token With verifyToken and Adding GET HTTP Request for user
1:07:18 Creating Backend - Getting user details
1:10:55 Creating Backend - How To send JWT token securely to frontend? - Using httpOnly cookie 
1:23:36 Creating Frontend- Installing React Application
1:25:20 Creating Frontend - Installing MaterialUI
1:26:43 Creating Frontend - Building Navigation Bar With Tab Links
1:31:47 Creating Frontend - Using React Router For Navigation
1:32:25 Creating Frontend - Adding Routes in application
1:37:32 Creating Frontend- Adding Signup Page
1:47:25 Creating Frontend - Installing axios to send HTTP Requests
1:47:46 Creating Frontend - Sending Signup HTTP POST Request
1:52:20 Creating Frontend - Creating Login Page
1:57:47 Creating Frontend - Adding Welcome User Page and Sending axios request with withCredentials property
2:04:11 Creating Frontend: Adding refresh Token route and sending refresh token request
2:22:10 Creating Frontend - Adding .env file in NodeJS Backend
2:25:15 Creating Frontend - Adding Logout Functionality With Redux
2:26:04 Creating Frontend - Installing and Configuring Redux
2:33:00 Creating Frontend - Adding Logout Route and Controller in Backend
2:41:52 Creating Frontend - Adding Protected Route (user)
2:43:16 Application Completes
2:43:30 Project Summary

Source Code: https://github.com/Nikhilthadani/MERN-authentication-authorization.git 

Subscribe: https://www.youtube.com/c/IndianCoders/featured 

#mern #javascript #react #nodejs #mongodb 

Advanced User Authentication & Authorization | Mern Authentication
Code  Geek

Code Geek

1664505688

MERN Stack Full Tutorial | MERN Stack Project

MERN Stack Full Tutorial & Project | Complete All-in-One Course | 8 Hours

This MERN Stack Full Tutorial & Project provides a complete all-in-one course with 8 hours of code and instruction to level up your web development skills. Think of this MERN Stack Full Tutorial Course as a full stack video textbook with 13 clearly defined chapters.

(00:00:00) Intro
(00:00:05) Welcome
(00:00:42) Chapter 1: MERN Stack Project
(00:28:13) Chapter 2: Middleware
(00:56:04) Chapter 3: MongoDB
(01:24:59) Chapter 4: Controllers
(02:08:14) Chapter 5: React JS
(02:42:15) Chapter 6: Redux & RTK Query
(03:16:54) Chapter 7: React & Redux Forms
(04:08:36) Chapter 8: Authentication vs Authorization
(04:45:17) Chapter 9: Login Auth
(05:18:49) Chapter 10: JWT Auth
(06:00:59) Chapter 11: Roles & Permissions
(06:44:17) Chapter 12: Refactoring
(07:30:19) Chapter 13: Deployment

All Resources for this MERN Stack Project: https://github.com/gitdagray/mern_stack_course 

Subscribe: https://www.youtube.com/c/DaveGrayTeachesCode/featured 

#mern  #stack  #javascript 

MERN Stack Full Tutorial | MERN Stack Project
Charles Cooper

Charles Cooper

1664357121

MERN Stack Chat App with Socket.IO

MERN Stack with Socket.io Chat App for Beginners

MERN Stack Socket.io chat application for beginners with project include MERN = Nodejs with Expressjs, React with React Router, Mongodb with Mongoose and socket.io for websocket thing

🌟 Course Contents 🌟
⏳ (00:00:00) Intro to course
⏳ (00:04:02) Course Outline
⏳ (00:07:43) Setup Nodejs
⏳ (00:13:16) First socket connection
⏳ (00:20:35) React with socket.io
⏳ (00:30:33) Send and receive message
⏳ (00:42:18) Make Chat Working
⏳ (00:51:17) Chat box design
⏳ (01:00:00) Message box design
⏳ (01:09:43) Typing event
⏳ (01:22:34) React router
⏳ (01:38:24) Join room
⏳ (01:47:26) Room chat
⏳ (01:57:53) Best practice Clean Code
⏳ (02:08:48) Dynamic room
⏳ (02:20:41) Rooms on MongoDB
⏳ (02:37:19) Dummy user
⏳ (02:45:25) Remove room
⏳ (03:00:07) File sharing

Source Code: https://github.com/bitfumes/mern-stack-socket-chat

#mern #socketio #mongodb #expressjs #node #react 

MERN Stack Chat App with Socket.IO
Dylan  Iqbal

Dylan Iqbal

1663816330

MERN Stack Tutorial for Beginners with Full Project

MERN Stack complete course with project include MERN = Nodejs with Expressjs, React with Redux, Mongodb with Mongoose and authentication with passportjs jwt library

What is the MERN stack?

The phrase MERN stack refers to the following technologies:

  • MongoDB, a cross-platform document-oriented database program
  • Express.js, a web application framework for Node.js
  • React, a JavaScript library for building user interfaces
  • Node.js, an open-source, cross-platform JavaScript run-time environment that executes JavaScript code outside of a browser

🌟 Course Contents 🌟
⏳ (00:00:00) Intro to course
⏳ (00:06:38) Course Outline
⏳ (00:11:38) Setup MERN project
⏳ (00:17:38) Setup MongoDB atlas
⏳ (00:25:20) Transaction form
⏳ (00:35:54) Handle CORS & Nodemon
⏳ (00:42:12) API body parser
⏳ (00:47:37) First transaction
⏳ (00:55:24) Fetch all transactions
⏳ (01:02:56) Express routes
⏳ (01:10:58) use material UI
⏳ (01:18:59) Design form 
⏳ (01:25:58) Submit form
⏳ (01:31:33) Transactions table
⏳ (01:40:31) Delete transactions
⏳ (01:52:47) Update design
⏳ (02:02:55) Update API
⏳ (02:09:30) React router dom
⏳ (02:21:53) Register user part 1
⏳ (02:34:10) Register user part 2
⏳ (02:45:50) Login user part 1
⏳ (02:54:18) Login user part 2
⏳ (03:00:14) Passport JWT authenticate
⏳ (03:13:22) DotEnv 
⏳ (03:23:23) Top level component middleware
⏳ (03:34:44) Validate token
⏳ (03:43:36) React redux store
⏳ (03:53:46) Auth store
⏳ (04:06:14) Express controllers
⏳ (04:14:40) Transactions of user
⏳ (04:43:55) Category to transaction
⏳ (04:39:07) Show all category
⏳ (04:46:59) Delete category
⏳ (04:57:12) Update & create category
⏳ (05:10:52) Monthly expense chart
⏳ (05:24:36) Deploy MERN stack to Heroku and Netlify

Source Code: https://github.com/bitfumes/mern-stack-2022


The MERN stack: A Complete Tutorial for Beginners

This tutorial is all about the MERN stack. We’ll outline the basics of the MERN stack and demonstrate how to use it by developing a simple CRUD application from scratch.

Server setup with Express.js and Node.js

To begin our MERN stack tutorial, we’ll show you how to set up a server with Express.js and Node.js.

npm package initialization

To create a project folder, enter the folder through the terminal, then run the following command:

$ npm init

Now it will ask you some questions about package name, version, entry point, etc. Hit enter if you want to keep the default. After that, you will get something like this:

Creating Our package.json File

Select yes and you’re ready to go. It creates a file named package.json.

Installing dependencies

Now, I would like to add some dependencies:

$ npm i express mongoose body-parser bcryptjs validation

Type or copy the command above and hit the enter button. You’ll see something like this:

Adding Project File Dependencies

  • bcryptjs is a password hashing function designed by Niels Provos and David Mazières
  • body-parser allows us to get the data throughout the request
  • express is our main framework
  • mongoose is used to connect/interact with MongoDB
  • validation (as its name implies) is used for validation

Now I want to add nodemon as a dev dependency. If you don’t want to add this, you can skip it — it’s optional.

$ npm i -D nodemon

nodemon is a utility that will monitor for any changes in your source and automatically restart your server.

At that point, your package.json should look like this:

package.json File With Dependencies

Setting the entry point

Now create a file named app.js for our entry point. You can create this from the project folder with the command below (on Mac):

$ touch app.js

Then paste the code below:

// app.js

const express = require('express');

const app = express();

app.get('/', (req, res) => res.send('Hello world!'));

const port = process.env.PORT || 8082;

app.listen(port, () => console.log(`Server running on port ${port}`));

Now, run the command

$ node app

You will see Server running on port 8082. You can also check it from the browser: open the browser and enter http://localhost:8082.

At this point, if we change anything, we need to restart the server manually. But if we set up nodemon, then we don’t have to restart it every time; nodemon will watch if there is any change and restart the server automatically.

So what you need to do for that is a little change to the scripts in our package.json file. See below:

// package.json

{
  "name": "mern_a_to_z",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "start": "node app.js",
    "app": "nodemon app.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/nurislam03/MERN_A_to_Z.git"
  },
  "author": "Nur Islam",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/nurislam03/MERN_A_to_Z/issues"
  },
  "homepage": "https://github.com/nurislam03/MERN_A_to_Z#readme",
  "dependencies": {
    "bcryptjs": "^2.4.3",
    "body-parser": "^1.19.0",
    "express": "^4.17.1",
    "mongoose": "^5.5.15",
    "validation": "0.0.1"
  },
  "devDependencies": {
    "nodemon": "^1.19.1"
  }
}

So, now you can run your project using this command:

$ npm run app

If you get any error at this point, then run the commands below:

$ npm install
$ npm run app

You will see the following changes in your terminal if everything goes right:

Running Project Successfully

Database management with MongoDB

Now it’s time to work on our MERN database setup with MongoDB. For simplicity, we will use MongoDB Atlas.

Creating an account for MongoDB Atlas

MongoDB Atlas is a fully managed cloud database developed by the same team that built MongoDB.

First, you need an account. Create one and follow the procedure. After creating an account, you will see something like this:

MongoDB Atlas Homescreen

Click on the Project 0 section (top left) and you will see a button for creating a new project. Create a project and select the project.

Now, click on the Build a Cluster button from the project you have created. It will show you all the information. At the bottom, you will see a section called Cluster Name, click on that and enter a name for the database, then hit the Create Cluster button.

After two to three minutes, if everything goes well, you will find something like this:

Creating A Cluster In MongoDB Atlas

Click on the CONNECT button and fill in the username and password form for your database.

Setting Up Our Connection

Now hit the Create MongoDB User button. You can also choose either your current IP address or a different IP address, it’s up to you.

Now, if you follow the CONNECT button or the Choose a connection method button, you will see some different methods. Select accordingly.

Connection Methods Options

In this case, select the Connect Your Application section.

Now you will get your database link, which we will use in our next step.

Connection String Output

Our database is ready — now we need to add it to our project.

Inside the project folder, create another folder named config and inside it create two files named default.json and db.js. Add the following code:

// default.json

{
  "mongoURI":
    "mongodb+srv://mern123:<password>@mernatoz-9kdpd.mongodb.net/test?retryWrites=true&w=majority"
}
 /* Replace <password> with your database password */

/* ------------------------------------------------------------------ */
// db.js

const mongoose = require('mongoose');
const config = require('config');
const db = config.get('mongoURI');

const connectDB = async () => {
  try {
    await mongoose.connect(
      db,
      {
        useNewUrlParser: true
      }
    );

    console.log('MongoDB is Connected...');
  } catch (err) {
    console.error(err.message);
    process.exit(1);
  }
};

module.exports = connectDB;

NOTE: We need a little change in our app.js file to connect to the database. Update your app.js with this:

// app.js

const express = require('express');
const connectDB = require('./config/db');

const app = express();

// Connect Database
connectDB();

app.get('/', (req, res) => res.send('Hello world!'));

const port = process.env.PORT || 8082;

app.listen(port, () => console.log(`Server running on port ${port}`));

We need another dependency package called config for the global variable to run our project. Use the following command to install it to the project:

$ npm i config

Now, you can run the project using the following command:

$ npm run app
Successfully Connected Server

Great! So far we are on the right track. Our database is successfully connected. Now time to complete the route setup, and after that, we will see how to create RESTful APIs.

Building RESTful APIs with the MERN stack

Create a folder named routes. In it, create another folder named api, which will hold all our APIs.

Inside the api folder, create a file named books.js. We will create some APIs here to show how it works in a moment.

Now update your books.js with the following code:

// routes/api/books.js

const express = require('express');
const router = express.Router();

// Load Book model
const Book = require('../../models/Book');

// @route GET api/books/test
// @description tests books route
// @access Public
router.get('/test', (req, res) => res.send('book route testing!'));

// @route GET api/books
// @description Get all books
// @access Public
router.get('/', (req, res) => {
  Book.find()
    .then(books => res.json(books))
    .catch(err => res.status(404).json({ nobooksfound: 'No Books found' }));
});

// @route GET api/books/:id
// @description Get single book by id
// @access Public
router.get('/:id', (req, res) => {
  Book.findById(req.params.id)
    .then(book => res.json(book))
    .catch(err => res.status(404).json({ nobookfound: 'No Book found' }));
});

// @route GET api/books
// @description add/save book
// @access Public
router.post('/', (req, res) => {
  Book.create(req.body)
    .then(book => res.json({ msg: 'Book added successfully' }))
    .catch(err => res.status(400).json({ error: 'Unable to add this book' }));
});

// @route GET api/books/:id
// @description Update book
// @access Public
router.put('/:id', (req, res) => {
  Book.findByIdAndUpdate(req.params.id, req.body)
    .then(book => res.json({ msg: 'Updated successfully' }))
    .catch(err =>
      res.status(400).json({ error: 'Unable to update the Database' })
    );
});

// @route GET api/books/:id
// @description Delete book by id
// @access Public
router.delete('/:id', (req, res) => {
  Book.findByIdAndRemove(req.params.id, req.body)
    .then(book => res.json({ mgs: 'Book entry deleted successfully' }))
    .catch(err => res.status(404).json({ error: 'No such a book' }));
});

module.exports = router;

Database model

In order to interact with our database, we need to create a model for each of our resources. So, create a folder called models in the root, and inside the models folder, create a file called Book.js and update it with this:

// models/Book.js

const mongoose = require('mongoose');

const BookSchema = new mongoose.Schema({
  title: {
    type: String,
    required: true
  },
  isbn: {
    type: String,
    required: true
  },
  author: {
    type: String,
    required: true
  },
  description: {
    type: String
  },
  published_date: {
    type: Date
  },
  publisher: {
    type: String
  },
  updated_date: {
    type: Date,
    default: Date.now
  }
});

module.exports = Book = mongoose.model('book', BookSchema);

Run the project to see if everything is fine at this point, and you can test all the APIs through Postman (note that before testing APIs using Postman, you need to run the project first). You can download Postman here.

Building the frontend

So far, so good! Now that we’ve set up our backend, it’s time to transition to the frontend part of this MERN stack tutorial.

In this section, we’ll use React to build our user interfaces. React is a JavaScript library for building user interfaces. It is maintained by Facebook and a community of individual developers and other companies.

We’ll use Create React App to generate our initial file setup. CRA is a comfortable environment for learning React and is the best way to start building applications in React. It offers a modern build setup with no configuration.

We’ll also use webpack and Babel to bundle our modules and compile our JavaScript, respectively. If you don’t know webpack or Babel well, no problem; you don’t need to install or configure tools like webpack or Babel. They’re preconfigured and hidden so that you can focus on the code. Just create a project, and you’re good to go.

You’ll also need any version of Node.js greater than 8.10 and any version of npm greater than 5.6 installed on your local development machine.

Setting up Create React App

Set any directory using a terminal where you want to keep all the files of this project and run the following command to get the initial setup file:

 $ npx create-react-app my-app

You can replace my-app with whatever you’d like to use as your project name. For example, my project name is mern_a_to_z_client, and my command is:

 $ npx create-react-app mern_a_to_z_client

Note: The project name must be in lowercase letters.

If everything goes right, then you will see something like the following image, where you will find some instructions along with the commands.

Project Successfully Created In Create React App

Before using any built-in command, we need to go inside the project folder.

 $ cd mern_a_to_z_client

Now that we are in the project directory, we can use those available commands. If you’re using Yarn:

$ yarn start

Or, if using npm:

$ npm start

To run the app in development mode, you can use any of the above commands, and you will see the following message in your terminal.

Running App In Development Mode

Now open http://localhost:3000 to view it in the browser. This page will automatically reload if you make changes to the code.

Viewing Our App In The Browser

Initial project structure

Inside the project directory, our initial file structure should look like this:

Our Initial Project Structure

Adding Bootstrap and Font Awesome to your React app

We have got our initial setup file for the front-end part. Now we can start integrating our back end with our front end. Before that, though, I want to add Bootstrap and Font Awesome’s CDN to our project.

Open the file called index.html, which is in the public folder mern_a_to_z_client/public/index.html, and replace everything with the following code:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->

    <!-- bootstrap css cdn -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

    <!-- fontawesome cdn -->
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css" integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ" crossorigin="anonymous">

    <title>MERN A to Z</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->

    <!-- bootstrap JS cdn -->
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>

  </body>
</html>

Frontend tasks and features

We will work with five different features:

  1. Add, create or save a new book
  2. Show all the books we have stored in the database
  3. Show a single book
  4. Update a book
  5. Delete a book

Dependencies packages installation

Now, use the following command to add some necessary dependencies:

$ npm install --save react-router-dom
$ npm install --save axios

Why Axios?

Axios is a lightweight HTTP client based similar to a Fetch API. Axios is a promise-based async/await library for readable asynchronous code. We can easily integrate with React, and it is effortless to use in any front-end framework.

We’ll call our APIs through Axios.

Package.json file

At this point, our package.json file should be similar to this; versions can be similar or different:

// MERN_A_to_Z_Client - package.json

{
  "name": "mern_a_to_z_client",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "axios": "^0.19.0",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-router-dom": "^5.0.1",
    "react-scripts": "3.0.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

Creating the component file

Inside the src folder (mern_a_to_z_client/src/), create another folder called components, and inside it, create five different files:

  1. CreateBook.js
  2. ShowBookList.js
  3. BookCard.js
  4. ShowBookDetails.js
  5. UpdateBookInfo.js

We will work with these five files a bit later.

Setup route

Open the folder called App.js inside the src folder (mern_a_to_z_client/src/App.js), and replace it with the following code:

import React, { Component } from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import './App.css';

import CreateBook from './components/CreateBook';
import ShowBookList from './components/ShowBookList';
import ShowBookDetails from './components/ShowBookDetails';
import UpdateBookInfo from './components/UpdateBookInfo';

class App extends Component {
  render() {
    return (
      <Router>
        <div>
          <Route exact path='/' component={ShowBookList} />
          <Route path='/create-book' component={CreateBook} />
          <Route path='/edit-book/:id' component={UpdateBookInfo} />
          <Route path='/show-book/:id' component={ShowBookDetails} />
        </div>
      </Router>
    );
  }
}

export default App;

Here, we define all the routes. For a specific path definition, its corresponding component will be rendered. We have not implemented these files/components yet — just completed the path setup.

Updating the CSS file

Update a CSS file called App.css in the src folder with the following code:

.App {
  text-align: center;
}

.App-logo {
  animation: App-logo-spin infinite 20s linear;
  height: 40vmin;
  pointer-events: none;
}

.App-header {
  background-color: #282c34;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: white;
}

.App-link {
  color: #61dafb;
}

@keyframes App-logo-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.CreateBook {
  background-color: #2c3e50;
  min-height: 100vh;
  color: white;
}

.ShowBookDetails {
  background-color: #2c3e50;
  min-height: 100vh;
  color: white;
}

.UpdateBookInfo {
  background-color: #2c3e50;
  min-height: 100vh;
  color: white;
}

.ShowBookList {
  background-color: #2c3e50;
  height: 100%;
  width: 100%;
  min-height: 100vh;
  min-width: 100px;
  color: white;
}


/* BookList Styles */
.list {
  display: grid;
  margin: 20px 0 50px 0;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: 1fr;
  grid-gap: 2em;
}

.card-container {
  width: 250px;
  border: 1px solid rgba(0,0,.125);
  margin: 0 auto;
  border-radius: 5px;
  overflow: hidden;
}

.desc {
  height: 130px;
  padding: 10px;
}

.desc h2 {
  font-size: 1em;
  font-weight: 400;
}

.desc h3, p {
  font-weight: 300;
}

.desc h3 {
  color: #6c757d;
  font-size: 1em;
  padding: 10px 0 10px 0;
}

Adding our feature components

Now it’s time to add feature components to our MERN stack project.

Create a new book

Our CreateBook.js file is responsible for adding, creating, or saving a new book or a book’s info. So, update CreateBook.js with the following code:

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import '../App.css';
import axios from 'axios';


class CreateBook extends Component {
  constructor() {
    super();
    this.state = {
      title: '',
      isbn:'',
      author:'',
      description:'',
      published_date:'',
      publisher:''
    };
  }

  onChange = e => {
    this.setState({ [e.target.name]: e.target.value });
  };

  onSubmit = e => {
    e.preventDefault();

    const data = {
      title: this.state.title,
      isbn: this.state.isbn,
      author: this.state.author,
      description: this.state.description,
      published_date: this.state.published_date,
      publisher: this.state.publisher
    };

    axios
      .post('http://localhost:8082/api/books', data)
      .then(res => {
        this.setState({
          title: '',
          isbn:'',
          author:'',
          description:'',
          published_date:'',
          publisher:''
        })
        this.props.history.push('/');
      })
      .catch(err => {
        console.log("Error in CreateBook!");
      })
  };

  render() {
    return (
      <div className="CreateBook">
        <div className="container">
          <div className="row">
            <div className="col-md-8 m-auto">
              <br />
              <Link to="/" className="btn btn-outline-warning float-left">
                  Show BooK List
              </Link>
            </div>
            <div className="col-md-8 m-auto">
              <h1 className="display-4 text-center">Add Book</h1>
              <p className="lead text-center">
                  Create new book
              </p>

              <form noValidate onSubmit={this.onSubmit}>
                <div className='form-group'>
                  <input
                    type='text'
                    placeholder='Title of the Book'
                    name='title'
                    className='form-control'
                    value={this.state.title}
                    onChange={this.onChange}
                  />
                </div>
                <br />

                <div className='form-group'>
                  <input
                    type='text'
                    placeholder='ISBN'
                    name='isbn'
                    className='form-control'
                    value={this.state.isbn}
                    onChange={this.onChange}
                  />
                </div>

                <div className='form-group'>
                  <input
                    type='text'
                    placeholder='Author'
                    name='author'
                    className='form-control'
                    value={this.state.author}
                    onChange={this.onChange}
                  />
                </div>

                <div className='form-group'>
                  <input
                    type='text'
                    placeholder='Describe this book'
                    name='description'
                    className='form-control'
                    value={this.state.description}
                    onChange={this.onChange}
                  />
                </div>

                <div className='form-group'>
                  <input
                    type='date'
                    placeholder='published_date'
                    name='published_date'
                    className='form-control'
                    value={this.state.published_date}
                    onChange={this.onChange}
                  />
                </div>
                <div className='form-group'>
                  <input
                    type='text'
                    placeholder='Publisher of this Book'
                    name='publisher'
                    className='form-control'
                    value={this.state.publisher}
                    onChange={this.onChange}
                  />
                </div>

                <input
                    type="submit"
                    className="btn btn-outline-warning btn-block mt-4"
                />
              </form>
          </div>
          </div>
        </div>
      </div>
    );
  }
}

export default CreateBook;

Show all books

The ShowBookList.js component will be responsible for showing all the books we already have stored in our database. Update ShowBookList.js with this code:

import React, { Component } from 'react';
import '../App.css';
import axios from 'axios';
import { Link } from 'react-router-dom';
import BookCard from './BookCard';

class ShowBookList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      books: []
    };
  }

  componentDidMount() {
    axios
      .get('http://localhost:8082/api/books')
      .then(res => {
        this.setState({
          books: res.data
        })
      })
      .catch(err =>{
        console.log('Error from ShowBookList');
      })
  };


  render() {
    const books = this.state.books;
    console.log("PrintBook: " + books);
    let bookList;

    if(!books) {
      bookList = "there is no book record!";
    } else {
      bookList = books.map((book, k) =>
        <BookCard book={book} key={k} />
      );
    }

    return (
      <div className="ShowBookList">
        <div className="container">
          <div className="row">
            <div className="col-md-12">
              <br />
              <h2 className="display-4 text-center">Books List</h2>
            </div>

            <div className="col-md-11">
              <Link to="/create-book" className="btn btn-outline-warning float-right">
                + Add New Book
              </Link>
              <br />
              <br />
              <hr />
            </div>

          </div>

          <div className="list">
                {bookList}
          </div>
        </div>
      </div>
    );
  }
}

export default ShowBookList;

Creating a card for each book

Here we use a functional component called BookCard.js, which takes a book’s info from ShowBookList.js and makes a card for each book. Write the following code to update your BookCard.js file:

import React from 'react';
import { Link } from 'react-router-dom';
import '../App.css';

const BookCard = (props) => {
    const  book  = props.book;

    return(
        <div className="card-container">
            <img src="https://commapress.co.uk/books/the-book-of-cairo/cairo-provisional-v3/image%2Fspan3" alt="" />
            <div className="desc">
                <h2>
                    <Link to={`/show-book/${book._id}`}>
                        { book.title }
                    </Link>
                </h2>
                <h3>{book.author}</h3>
                <p>{book.description}</p>
            </div>
        </div>
    )
};

export default BookCard;

NOTE: Here, I used the same img src for each book, since each book’s respective image may not always be available. Change the image source, and you can also use a different image for each book.

Show a book’s info

The ShowBookDetails component has one task: it shows all the info we have about any book. We have both delete and edit buttons here to get access.

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import '../App.css';
import axios from 'axios';

class showBookDetails extends Component {
  constructor(props) {
    super(props);
    this.state = {
      book: {}
    };
  }

  componentDidMount() {
    // console.log("Print id: " + this.props.match.params.id);
    axios
      .get('http://localhost:8082/api/books/'+this.props.match.params.id)
      .then(res => {
        // console.log("Print-showBookDetails-API-response: " + res.data);
        this.setState({
          book: res.data
        })
      })
      .catch(err => {
        console.log("Error from ShowBookDetails");
      })
  };

  onDeleteClick (id) {
    axios
      .delete('http://localhost:8082/api/books/'+id)
      .then(res => {
        this.props.history.push("/");
      })
      .catch(err => {
        console.log("Error form ShowBookDetails_deleteClick");
      })
  };


  render() {

    const book = this.state.book;
    let BookItem = <div>
      <table className="table table-hover table-dark">
        {/* <thead>
          <tr>
            <th scope="col">#</th>
            <th scope="col">First</th>
            <th scope="col">Last</th>
            <th scope="col">Handle</th>
          </tr>
        </thead> */}
        <tbody>
          <tr>
            <th scope="row">1</th>
            <td>Title</td>
            <td>{ book.title }</td>
          </tr>
          <tr>
            <th scope="row">2</th>
            <td>Author</td>
            <td>{ book.author }</td>
          </tr>
          <tr>
            <th scope="row">3</th>
            <td>ISBN</td>
            <td>{ book.isbn }</td>
          </tr>
          <tr>
            <th scope="row">4</th>
            <td>Publisher</td>
            <td>{ book.publisher }</td>
          </tr>
          <tr>
            <th scope="row">5</th>
            <td>Published Date</td>
            <td>{ book.published_date }</td>
          </tr>
          <tr>
            <th scope="row">6</th>
            <td>Description</td>
            <td>{ book.description }</td>
          </tr>
        </tbody>
      </table>
    </div>

    return (
      <div className="ShowBookDetails">
        <div className="container">
          <div className="row">
            <div className="col-md-10 m-auto">
              <br /> <br />
              <Link to="/" className="btn btn-outline-warning float-left">
                  Show Book List
              </Link>
            </div>
            <br />
            <div className="col-md-8 m-auto">
              <h1 className="display-4 text-center">Book's Record</h1>
              <p className="lead text-center">
                  View Book's Info
              </p>
              <hr /> <br />
            </div>
          </div>
          <div>
            { BookItem }
          </div>

          <div className="row">
            <div className="col-md-6">
              <button type="button" className="btn btn-outline-danger btn-lg btn-block" onClick={this.onDeleteClick.bind(this,book._id)}>Delete Book</button><br />
            </div>

            <div className="col-md-6">
              <Link to={`/edit-book/${book._id}`} className="btn btn-outline-info btn-lg btn-block">
                    Edit Book
              </Link>
              <br />
            </div>

          </div>
            {/* <br />
            <button type="button" class="btn btn-outline-info btn-lg btn-block">Edit Book</button>
            <button type="button" class="btn btn-outline-danger btn-lg btn-block">Delete Book</button> */}

        </div>
      </div>
    );
  }
}

export default showBookDetails;

Update a book’s info

UpdateBookInfo.js, as its name indicates, is responsible for updating a book’s info. An Edit Book button will trigger this component to perform. After clicking Edit Book, we will see a form with the old info, which we will be able to edit or replace.

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
import '../App.css';

class UpdateBookInfo extends Component {
  constructor(props) {
    super(props);
    this.state = {
      title: '',
      isbn: '',
      author: '',
      description: '',
      published_date: '',
      publisher: ''
    };
  }

  componentDidMount() {
    // console.log("Print id: " + this.props.match.params.id);
    axios
      .get('http://localhost:8082/api/books/'+this.props.match.params.id)
      .then(res => {
        // this.setState({...this.state, book: res.data})
        this.setState({
          title: res.data.title,
          isbn: res.data.isbn,
          author: res.data.author,
          description: res.data.description,
          published_date: res.data.published_date,
          publisher: res.data.publisher
        })
      })
      .catch(err => {
        console.log("Error from UpdateBookInfo");
      })
  };

  onChange = e => {
    this.setState({ [e.target.name]: e.target.value });
  };

  onSubmit = e => {
    e.preventDefault();

    const data = {
      title: this.state.title,
      isbn: this.state.isbn,
      author: this.state.author,
      description: this.state.description,
      published_date: this.state.published_date,
      publisher: this.state.publisher
    };

    axios
      .put('http://localhost:8082/api/books/'+this.props.match.params.id, data)
      .then(res => {
        this.props.history.push('/show-book/'+this.props.match.params.id);
      })
      .catch(err => {
        console.log("Error in UpdateBookInfo!");
      })
  };


  render() {
    return (
      <div className="UpdateBookInfo">
        <div className="container">
          <div className="row">
            <div className="col-md-8 m-auto">
              <br />
              <Link to="/" className="btn btn-outline-warning float-left">
                  Show BooK List
              </Link>
            </div>
            <div className="col-md-8 m-auto">
              <h1 className="display-4 text-center">Edit Book</h1>
              <p className="lead text-center">
                  Update Book's Info
              </p>
            </div>
          </div>

          <div className="col-md-8 m-auto">
          <form noValidate onSubmit={this.onSubmit}>
            <div className='form-group'>
              <label htmlFor="title">Title</label>
              <input
                type='text'
                placeholder='Title of the Book'
                name='title'
                className='form-control'
                value={this.state.title}
                onChange={this.onChange}
              />
            </div>
            <br />

            <div className='form-group'>
            <label htmlFor="isbn">ISBN</label>
              <input
                type='text'
                placeholder='ISBN'
                name='isbn'
                className='form-control'
                value={this.state.isbn}
                onChange={this.onChange}
              />
            </div>

            <div className='form-group'>
            <label htmlFor="author">Author</label>
              <input
                type='text'
                placeholder='Author'
                name='author'
                className='form-control'
                value={this.state.author}
                onChange={this.onChange}
              />
            </div>

            <div className='form-group'>
            <label htmlFor="description">Description</label>
              <input
                type='text'
                placeholder='Describe this book'
                name='description'
                className='form-control'
                value={this.state.description}
                onChange={this.onChange}
              />
            </div>

            <div className='form-group'>
            <label htmlFor="published_date">Published Date</label>
              <input
                type='date'
                placeholder='published_date'
                name='published_date'
                className='form-control'
                value={this.state.published_date}
                onChange={this.onChange}
              />
            </div>
            <div className='form-group'>
            <label htmlFor="publisher">Publisher</label>
              <input
                type='text'
                placeholder='Publisher of this Book'
                name='publisher'
                className='form-control'
                value={this.state.publisher}
                onChange={this.onChange}
              />
            </div>

            <button type="submit" className="btn btn-outline-info btn-lg btn-block">Update Book</button>
            </form>
          </div>

        </div>
      </div>
    );
  }
}

export default UpdateBookInfo;

Connecting the frontend to the backend

We just implemented all of our components! Now we need a little change in our server-side (back-end) project.

Changes required on the backend

If we try to call our back-end API from the front-end part, it gets an error that says: “Access to XMLHttpRequest at ‘http://localhost:8082/api/books&#8217; from origin ‘http://localhost:3000&#8217; has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.”

To solve this, we need to install cors in our back-end (server-side) project. Go to the project folder (e.g., MERN_A_to_Z) and run:

$ npm install cors

Now, update app.js (the back end’s entry point) with the following code:

// app.js

const express = require('express');
const connectDB = require('./config/db');
var cors = require('cors');

// routes
const books = require('./routes/api/books');

const app = express();

// Connect Database
connectDB();

// cors
app.use(cors({ origin: true, credentials: true }));

// Init Middleware
app.use(express.json({ extended: false }));

app.get('/', (req, res) => res.send('Hello world!'));

// use Routes
app.use('/api/books', books);

const port = process.env.PORT || 8082;

app.listen(port, () => console.log(`Server running on port ${port}`));

Running the frontend and backend

Follow the steps below to run both the frontend and backend of our MERN stack example.

Run the server

Now, run the server (inside the project folder):

$ npm run app

If you get any error, then follow the commands below (inside the project folder):

$ npm install
$ npm run app

Run the client

From the front-end project directory, run the command below:

$ npm start

If you get an error, again, follow the same commands below:

$ npm install
$ npm start

Testing our MERN stack app in the browser

Let’s check everything in the browser. Open http://localhost:3000 in your browser. Now you can add a book, delete a book, show the list of books, and edit books. The following routes should perform accordingly:

Add a new book: http://localhost:3000/create-book

The Add Book Page

Show the list of books: http://localhost:3000/

The Books List Page

Show any book’s info: http://localhost:3000/show-book/:id

Show Book Details Page

Update a book’s info: http://localhost:3000/edit-book/:id

The Edit Book Page

Congratulations! You have successfully completed this MERN stack tutorial.

You can visit my GitHub to see both the server-side and client-side portions of this MERN stack tutorial. You can also find the complete repo for our MERN stack example app on GitHub.

#mern #mongodb #react #expressjs #node #redux #mongoose #jwt #passportjs 

MERN Stack Tutorial for Beginners with Full Project
Thomas  Granger

Thomas Granger

1663294502

Learn the MERN Stack: Build a Simple CRUD App from Scratch

Learn the MERN stack by building a simple CRUD application from scratch. Learn the fundamental concepts of MongoDB, Express.js, React.js, and Node.js with hands-on.

Meanwhile, we’ll cover the following MERN stack topics:

  • What is the MERN stack?
  • Server setup with Express.js and Node.js
  • Database management with MongoDB
  • Building RESTful APIs with the MERN stack
  • Building the frontend
  • Setting up Create React App
  • Initial project structure
  • Frontend tasks and features
  • Adding feature components
  • Connecting the frontend and backend
  • Running the frontend and backend
  • Testing our MERN stack app in the browser

This demo is designed to highlight the MERN setup. The objective is to develop a simple project with the best possible structure so that you can use it as a boilerplate and elevate your MERN stack projects to meet industry standards.

What is the MERN stack?

The phrase MERN stack refers to the following technologies:

  • MongoDB, a cross-platform document-oriented database program
  • Express.js, a web application framework for Node.js
  • React, a JavaScript library for building user interfaces
  • Node.js, an open-source, cross-platform JavaScript run-time environment that executes JavaScript code outside of a browser

If you’re a visual learner (and have some time on your hands), check out this comprehensive, up-to-date MERN stack video tutorial:

Server setup with Express.js and Node.js

To begin our MERN stack tutorial, we’ll show you how to set up a server with Express.js and Node.js.

npm package initialization

To create a project folder, enter the folder through the terminal, then run the following command:

$ npm init

Now it will ask you some questions about package name, version, entry point, etc. Hit enter if you want to keep the default. After that, you will get something like this:

Creating Our package.json File

Select yes and you’re ready to go. It creates a file named package.json.

Installing dependencies

Now, I would like to add some dependencies:

$ npm i express mongoose body-parser bcryptjs validation

Type or copy the command above and hit the enter button. You’ll see something like this:

Adding Project File Dependencies

  • bcryptjs is a password hashing function designed by Niels Provos and David Mazières
  • body-parser allows us to get the data throughout the request
  • express is our main framework
  • mongoose is used to connect/interact with MongoDB
  • validation (as its name implies) is used for validation

Now I want to add nodemon as a dev dependency. If you don’t want to add this, you can skip it — it’s optional.

$ npm i -D nodemon

nodemon is a utility that will monitor for any changes in your source and automatically restart your server.

At that point, your package.json should look like this:

package.json File With Dependencies

Setting the entry point

Now create a file named app.js for our entry point. You can create this from the project folder with the command below (on Mac):

$ touch app.js

Then paste the code below:

// app.js

const express = require('express');

const app = express();

app.get('/', (req, res) => res.send('Hello world!'));

const port = process.env.PORT || 8082;

app.listen(port, () => console.log(`Server running on port ${port}`));

Now, run the command

$ node app

You will see Server running on port 8082. You can also check it from the browser: open the browser and enter http://localhost:8082.

At this point, if we change anything, we need to restart the server manually. But if we set up nodemon, then we don’t have to restart it every time; nodemon will watch if there is any change and restart the server automatically.

So what you need to do for that is a little change to the scripts in our package.json file. See below:

// package.json

{
  "name": "mern_a_to_z",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "start": "node app.js",
    "app": "nodemon app.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/nurislam03/MERN_A_to_Z.git"
  },
  "author": "Nur Islam",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/nurislam03/MERN_A_to_Z/issues"
  },
  "homepage": "https://github.com/nurislam03/MERN_A_to_Z#readme",
  "dependencies": {
    "bcryptjs": "^2.4.3",
    "body-parser": "^1.19.0",
    "express": "^4.17.1",
    "mongoose": "^5.5.15",
    "validation": "0.0.1"
  },
  "devDependencies": {
    "nodemon": "^1.19.1"
  }
}

So, now you can run your project using this command:

$ npm run app

If you get any error at this point, then run the commands below:

$ npm install
$ npm run app

You will see the following changes in your terminal if everything goes right:

Running Project Successfully

Database management with MongoDB

Now it’s time to work on our MERN database setup with MongoDB. For simplicity, we will use MongoDB Atlas.

Creating an account for MongoDB Atlas

MongoDB Atlas is a fully managed cloud database developed by the same team that built MongoDB.

First, you need an account. Create one and follow the procedure. After creating an account, you will see something like this:

MongoDB Atlas Homescreen

Click on the Project 0 section (top left) and you will see a button for creating a new project. Create a project and select the project.

Now, click on the Build a Cluster button from the project you have created. It will show you all the information. At the bottom, you will see a section called Cluster Name, click on that and enter a name for the database, then hit the Create Cluster button.

After two to three minutes, if everything goes well, you will find something like this:

Creating A Cluster In MongoDB Atlas

Click on the CONNECT button and fill in the username and password form for your database.

Setting Up Our Connection

Now hit the Create MongoDB User button. You can also choose either your current IP address or a different IP address, it’s up to you.

Now, if you follow the CONNECT button or the Choose a connection method button, you will see some different methods. Select accordingly.

Connection Methods Options

In this case, select the Connect Your Application section.

Now you will get your database link, which we will use in our next step.

Connection String Output

Our database is ready — now we need to add it to our project.

Inside the project folder, create another folder named config and inside it create two files named default.json and db.js. Add the following code:

// default.json

{
  "mongoURI":
    "mongodb+srv://mern123:<password>@mernatoz-9kdpd.mongodb.net/test?retryWrites=true&w=majority"
}
 /* Replace <password> with your database password */

/* ------------------------------------------------------------------ */
// db.js

const mongoose = require('mongoose');
const config = require('config');
const db = config.get('mongoURI');

const connectDB = async () => {
  try {
    await mongoose.connect(
      db,
      {
        useNewUrlParser: true
      }
    );

    console.log('MongoDB is Connected...');
  } catch (err) {
    console.error(err.message);
    process.exit(1);
  }
};

module.exports = connectDB;

NOTE: We need a little change in our app.js file to connect to the database. Update your app.js with this:

// app.js

const express = require('express');
const connectDB = require('./config/db');

const app = express();

// Connect Database
connectDB();

app.get('/', (req, res) => res.send('Hello world!'));

const port = process.env.PORT || 8082;

app.listen(port, () => console.log(`Server running on port ${port}`));

We need another dependency package called config for the global variable to run our project. Use the following command to install it to the project:

$ npm i config

Now, you can run the project using the following command:

$ npm run app
Successfully Connected Server

Great! So far we are on the right track. Our database is successfully connected. Now time to complete the route setup, and after that, we will see how to create RESTful APIs.

Building RESTful APIs with the MERN stack

Create a folder named routes. In it, create another folder named api, which will hold all our APIs.

Inside the api folder, create a file named books.js. We will create some APIs here to show how it works in a moment.

Now update your books.js with the following code:

// routes/api/books.js

const express = require('express');
const router = express.Router();

// Load Book model
const Book = require('../../models/Book');

// @route GET api/books/test
// @description tests books route
// @access Public
router.get('/test', (req, res) => res.send('book route testing!'));

// @route GET api/books
// @description Get all books
// @access Public
router.get('/', (req, res) => {
  Book.find()
    .then(books => res.json(books))
    .catch(err => res.status(404).json({ nobooksfound: 'No Books found' }));
});

// @route GET api/books/:id
// @description Get single book by id
// @access Public
router.get('/:id', (req, res) => {
  Book.findById(req.params.id)
    .then(book => res.json(book))
    .catch(err => res.status(404).json({ nobookfound: 'No Book found' }));
});

// @route GET api/books
// @description add/save book
// @access Public
router.post('/', (req, res) => {
  Book.create(req.body)
    .then(book => res.json({ msg: 'Book added successfully' }))
    .catch(err => res.status(400).json({ error: 'Unable to add this book' }));
});

// @route GET api/books/:id
// @description Update book
// @access Public
router.put('/:id', (req, res) => {
  Book.findByIdAndUpdate(req.params.id, req.body)
    .then(book => res.json({ msg: 'Updated successfully' }))
    .catch(err =>
      res.status(400).json({ error: 'Unable to update the Database' })
    );
});

// @route GET api/books/:id
// @description Delete book by id
// @access Public
router.delete('/:id', (req, res) => {
  Book.findByIdAndRemove(req.params.id, req.body)
    .then(book => res.json({ mgs: 'Book entry deleted successfully' }))
    .catch(err => res.status(404).json({ error: 'No such a book' }));
});

module.exports = router;

Database model

In order to interact with our database, we need to create a model for each of our resources. So, create a folder called models in the root, and inside the models folder, create a file called Book.js and update it with this:

// models/Book.js

const mongoose = require('mongoose');

const BookSchema = new mongoose.Schema({
  title: {
    type: String,
    required: true
  },
  isbn: {
    type: String,
    required: true
  },
  author: {
    type: String,
    required: true
  },
  description: {
    type: String
  },
  published_date: {
    type: Date
  },
  publisher: {
    type: String
  },
  updated_date: {
    type: Date,
    default: Date.now
  }
});

module.exports = Book = mongoose.model('book', BookSchema);

Run the project to see if everything is fine at this point, and you can test all the APIs through Postman (note that before testing APIs using Postman, you need to run the project first). You can download Postman here.


Building the frontend

So far, so good! Now that we’ve set up our backend, it’s time to transition to the frontend part of this MERN stack tutorial.

In this section, we’ll use React to build our user interfaces. React is a JavaScript library for building user interfaces. It is maintained by Facebook and a community of individual developers and other companies.

We’ll use Create React App to generate our initial file setup. CRA is a comfortable environment for learning React and is the best way to start building applications in React. It offers a modern build setup with no configuration.

We’ll also use webpack and Babel to bundle our modules and compile our JavaScript, respectively. If you don’t know webpack or Babel well, no problem; you don’t need to install or configure tools like webpack or Babel. They’re preconfigured and hidden so that you can focus on the code. Just create a project, and you’re good to go.

You’ll also need any version of Node.js greater than 8.10 and any version of npm greater than 5.6 installed on your local development machine.

Setting up Create React App

Set any directory using a terminal where you want to keep all the files of this project and run the following command to get the initial setup file:

 $ npx create-react-app my-app

You can replace my-app with whatever you’d like to use as your project name. For example, my project name is mern_a_to_z_client, and my command is:

 $ npx create-react-app mern_a_to_z_client

Note: The project name must be in lowercase letters.

If everything goes right, then you will see something like the following image, where you will find some instructions along with the commands.

Project Successfully Created In Create React App

Before using any built-in command, we need to go inside the project folder.

 $ cd mern_a_to_z_client

Now that we are in the project directory, we can use those available commands. If you’re using Yarn:

$ yarn start

Or, if using npm:

$ npm start

To run the app in development mode, you can use any of the above commands, and you will see the following message in your terminal.

Running App In Development Mode

Now open http://localhost:3000 to view it in the browser. This page will automatically reload if you make changes to the code.

Viewing Our App In The Browser

Initial project structure

Inside the project directory, our initial file structure should look like this:

Our Initial Project Structure

Adding Bootstrap and Font Awesome to your React app

We have got our initial setup file for the front-end part. Now we can start integrating our back end with our front end. Before that, though, I want to add Bootstrap and Font Awesome’s CDN to our project.

Open the file called index.html, which is in the public folder mern_a_to_z_client/public/index.html, and replace everything with the following code:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->

    <!-- bootstrap css cdn -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

    <!-- fontawesome cdn -->
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css" integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ" crossorigin="anonymous">

    <title>MERN A to Z</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->

    <!-- bootstrap JS cdn -->
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>

  </body>
</html>

Frontend tasks and features

We will work with five different features:

  1. Add, create or save a new book
  2. Show all the books we have stored in the database
  3. Show a single book
  4. Update a book
  5. Delete a book

Dependencies packages installation

Now, use the following command to add some necessary dependencies:

$ npm install --save react-router-dom
$ npm install --save axios

Why Axios?

Axios is a lightweight HTTP client based similar to a Fetch API. Axios is a promise-based async/await library for readable asynchronous code. We can easily integrate with React, and it is effortless to use in any front-end framework.

We’ll call our APIs through Axios.

Package.json file

At this point, our package.json file should be similar to this; versions can be similar or different:

// MERN_A_to_Z_Client - package.json

{
  "name": "mern_a_to_z_client",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "axios": "^0.19.0",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-router-dom": "^5.0.1",
    "react-scripts": "3.0.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

Creating the component file

Inside the src folder (mern_a_to_z_client/src/), create another folder called components, and inside it, create five different files:

  1. CreateBook.js
  2. ShowBookList.js
  3. BookCard.js
  4. ShowBookDetails.js
  5. UpdateBookInfo.js

We will work with these five files a bit later.

Setup route

Open the folder called App.js inside the src folder (mern_a_to_z_client/src/App.js), and replace it with the following code:

import React, { Component } from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import './App.css';

import CreateBook from './components/CreateBook';
import ShowBookList from './components/ShowBookList';
import ShowBookDetails from './components/ShowBookDetails';
import UpdateBookInfo from './components/UpdateBookInfo';

class App extends Component {
  render() {
    return (
      <Router>
        <div>
          <Route exact path='/' component={ShowBookList} />
          <Route path='/create-book' component={CreateBook} />
          <Route path='/edit-book/:id' component={UpdateBookInfo} />
          <Route path='/show-book/:id' component={ShowBookDetails} />
        </div>
      </Router>
    );
  }
}

export default App;

Here, we define all the routes. For a specific path definition, its corresponding component will be rendered. We have not implemented these files/components yet — just completed the path setup.

Updating the CSS file

Update a CSS file called App.css in the src folder with the following code:

.App {
  text-align: center;
}

.App-logo {
  animation: App-logo-spin infinite 20s linear;
  height: 40vmin;
  pointer-events: none;
}

.App-header {
  background-color: #282c34;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: white;
}

.App-link {
  color: #61dafb;
}

@keyframes App-logo-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.CreateBook {
  background-color: #2c3e50;
  min-height: 100vh;
  color: white;
}

.ShowBookDetails {
  background-color: #2c3e50;
  min-height: 100vh;
  color: white;
}

.UpdateBookInfo {
  background-color: #2c3e50;
  min-height: 100vh;
  color: white;
}

.ShowBookList {
  background-color: #2c3e50;
  height: 100%;
  width: 100%;
  min-height: 100vh;
  min-width: 100px;
  color: white;
}


/* BookList Styles */
.list {
  display: grid;
  margin: 20px 0 50px 0;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: 1fr;
  grid-gap: 2em;
}

.card-container {
  width: 250px;
  border: 1px solid rgba(0,0,.125);
  margin: 0 auto;
  border-radius: 5px;
  overflow: hidden;
}

.desc {
  height: 130px;
  padding: 10px;
}

.desc h2 {
  font-size: 1em;
  font-weight: 400;
}

.desc h3, p {
  font-weight: 300;
}

.desc h3 {
  color: #6c757d;
  font-size: 1em;
  padding: 10px 0 10px 0;
}

Adding our feature components

Now it’s time to add feature components to our MERN stack project.

Create a new book

Our CreateBook.js file is responsible for adding, creating, or saving a new book or a book’s info. So, update CreateBook.js with the following code:

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import '../App.css';
import axios from 'axios';


class CreateBook extends Component {
  constructor() {
    super();
    this.state = {
      title: '',
      isbn:'',
      author:'',
      description:'',
      published_date:'',
      publisher:''
    };
  }

  onChange = e => {
    this.setState({ [e.target.name]: e.target.value });
  };

  onSubmit = e => {
    e.preventDefault();

    const data = {
      title: this.state.title,
      isbn: this.state.isbn,
      author: this.state.author,
      description: this.state.description,
      published_date: this.state.published_date,
      publisher: this.state.publisher
    };

    axios
      .post('http://localhost:8082/api/books', data)
      .then(res => {
        this.setState({
          title: '',
          isbn:'',
          author:'',
          description:'',
          published_date:'',
          publisher:''
        })
        this.props.history.push('/');
      })
      .catch(err => {
        console.log("Error in CreateBook!");
      })
  };

  render() {
    return (
      <div className="CreateBook">
        <div className="container">
          <div className="row">
            <div className="col-md-8 m-auto">
              <br />
              <Link to="/" className="btn btn-outline-warning float-left">
                  Show BooK List
              </Link>
            </div>
            <div className="col-md-8 m-auto">
              <h1 className="display-4 text-center">Add Book</h1>
              <p className="lead text-center">
                  Create new book
              </p>

              <form noValidate onSubmit={this.onSubmit}>
                <div className='form-group'>
                  <input
                    type='text'
                    placeholder='Title of the Book'
                    name='title'
                    className='form-control'
                    value={this.state.title}
                    onChange={this.onChange}
                  />
                </div>
                <br />

                <div className='form-group'>
                  <input
                    type='text'
                    placeholder='ISBN'
                    name='isbn'
                    className='form-control'
                    value={this.state.isbn}
                    onChange={this.onChange}
                  />
                </div>

                <div className='form-group'>
                  <input
                    type='text'
                    placeholder='Author'
                    name='author'
                    className='form-control'
                    value={this.state.author}
                    onChange={this.onChange}
                  />
                </div>

                <div className='form-group'>
                  <input
                    type='text'
                    placeholder='Describe this book'
                    name='description'
                    className='form-control'
                    value={this.state.description}
                    onChange={this.onChange}
                  />
                </div>

                <div className='form-group'>
                  <input
                    type='date'
                    placeholder='published_date'
                    name='published_date'
                    className='form-control'
                    value={this.state.published_date}
                    onChange={this.onChange}
                  />
                </div>
                <div className='form-group'>
                  <input
                    type='text'
                    placeholder='Publisher of this Book'
                    name='publisher'
                    className='form-control'
                    value={this.state.publisher}
                    onChange={this.onChange}
                  />
                </div>

                <input
                    type="submit"
                    className="btn btn-outline-warning btn-block mt-4"
                />
              </form>
          </div>
          </div>
        </div>
      </div>
    );
  }
}

export default CreateBook;

Show all books

The ShowBookList.js component will be responsible for showing all the books we already have stored in our database. Update ShowBookList.js with this code:

import React, { Component } from 'react';
import '../App.css';
import axios from 'axios';
import { Link } from 'react-router-dom';
import BookCard from './BookCard';

class ShowBookList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      books: []
    };
  }

  componentDidMount() {
    axios
      .get('http://localhost:8082/api/books')
      .then(res => {
        this.setState({
          books: res.data
        })
      })
      .catch(err =>{
        console.log('Error from ShowBookList');
      })
  };


  render() {
    const books = this.state.books;
    console.log("PrintBook: " + books);
    let bookList;

    if(!books) {
      bookList = "there is no book record!";
    } else {
      bookList = books.map((book, k) =>
        <BookCard book={book} key={k} />
      );
    }

    return (
      <div className="ShowBookList">
        <div className="container">
          <div className="row">
            <div className="col-md-12">
              <br />
              <h2 className="display-4 text-center">Books List</h2>
            </div>

            <div className="col-md-11">
              <Link to="/create-book" className="btn btn-outline-warning float-right">
                + Add New Book
              </Link>
              <br />
              <br />
              <hr />
            </div>

          </div>

          <div className="list">
                {bookList}
          </div>
        </div>
      </div>
    );
  }
}

export default ShowBookList;

Creating a card for each book

Here we use a functional component called BookCard.js, which takes a book’s info from ShowBookList.js and makes a card for each book. Write the following code to update your BookCard.js file:

import React from 'react';
import { Link } from 'react-router-dom';
import '../App.css';

const BookCard = (props) => {
    const  book  = props.book;

    return(
        <div className="card-container">
            <img src="https://commapress.co.uk/books/the-book-of-cairo/cairo-provisional-v3/image%2Fspan3" alt="" />
            <div className="desc">
                <h2>
                    <Link to={`/show-book/${book._id}`}>
                        { book.title }
                    </Link>
                </h2>
                <h3>{book.author}</h3>
                <p>{book.description}</p>
            </div>
        </div>
    )
};

export default BookCard;

NOTE: Here, I used the same img src for each book, since each book’s respective image may not always be available. Change the image source, and you can also use a different image for each book.

Show a book’s info

The ShowBookDetails component has one task: it shows all the info we have about any book. We have both delete and edit buttons here to get access.

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import '../App.css';
import axios from 'axios';

class showBookDetails extends Component {
  constructor(props) {
    super(props);
    this.state = {
      book: {}
    };
  }

  componentDidMount() {
    // console.log("Print id: " + this.props.match.params.id);
    axios
      .get('http://localhost:8082/api/books/'+this.props.match.params.id)
      .then(res => {
        // console.log("Print-showBookDetails-API-response: " + res.data);
        this.setState({
          book: res.data
        })
      })
      .catch(err => {
        console.log("Error from ShowBookDetails");
      })
  };

  onDeleteClick (id) {
    axios
      .delete('http://localhost:8082/api/books/'+id)
      .then(res => {
        this.props.history.push("/");
      })
      .catch(err => {
        console.log("Error form ShowBookDetails_deleteClick");
      })
  };


  render() {

    const book = this.state.book;
    let BookItem = <div>
      <table className="table table-hover table-dark">
        {/* <thead>
          <tr>
            <th scope="col">#</th>
            <th scope="col">First</th>
            <th scope="col">Last</th>
            <th scope="col">Handle</th>
          </tr>
        </thead> */}
        <tbody>
          <tr>
            <th scope="row">1</th>
            <td>Title</td>
            <td>{ book.title }</td>
          </tr>
          <tr>
            <th scope="row">2</th>
            <td>Author</td>
            <td>{ book.author }</td>
          </tr>
          <tr>
            <th scope="row">3</th>
            <td>ISBN</td>
            <td>{ book.isbn }</td>
          </tr>
          <tr>
            <th scope="row">4</th>
            <td>Publisher</td>
            <td>{ book.publisher }</td>
          </tr>
          <tr>
            <th scope="row">5</th>
            <td>Published Date</td>
            <td>{ book.published_date }</td>
          </tr>
          <tr>
            <th scope="row">6</th>
            <td>Description</td>
            <td>{ book.description }</td>
          </tr>
        </tbody>
      </table>
    </div>

    return (
      <div className="ShowBookDetails">
        <div className="container">
          <div className="row">
            <div className="col-md-10 m-auto">
              <br /> <br />
              <Link to="/" className="btn btn-outline-warning float-left">
                  Show Book List
              </Link>
            </div>
            <br />
            <div className="col-md-8 m-auto">
              <h1 className="display-4 text-center">Book's Record</h1>
              <p className="lead text-center">
                  View Book's Info
              </p>
              <hr /> <br />
            </div>
          </div>
          <div>
            { BookItem }
          </div>

          <div className="row">
            <div className="col-md-6">
              <button type="button" className="btn btn-outline-danger btn-lg btn-block" onClick={this.onDeleteClick.bind(this,book._id)}>Delete Book</button><br />
            </div>

            <div className="col-md-6">
              <Link to={`/edit-book/${book._id}`} className="btn btn-outline-info btn-lg btn-block">
                    Edit Book
              </Link>
              <br />
            </div>

          </div>
            {/* <br />
            <button type="button" class="btn btn-outline-info btn-lg btn-block">Edit Book</button>
            <button type="button" class="btn btn-outline-danger btn-lg btn-block">Delete Book</button> */}

        </div>
      </div>
    );
  }
}

export default showBookDetails;

Update a book’s info

UpdateBookInfo.js, as its name indicates, is responsible for updating a book’s info. An Edit Book button will trigger this component to perform. After clicking Edit Book, we will see a form with the old info, which we will be able to edit or replace.

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
import '../App.css';

class UpdateBookInfo extends Component {
  constructor(props) {
    super(props);
    this.state = {
      title: '',
      isbn: '',
      author: '',
      description: '',
      published_date: '',
      publisher: ''
    };
  }

  componentDidMount() {
    // console.log("Print id: " + this.props.match.params.id);
    axios
      .get('http://localhost:8082/api/books/'+this.props.match.params.id)
      .then(res => {
        // this.setState({...this.state, book: res.data})
        this.setState({
          title: res.data.title,
          isbn: res.data.isbn,
          author: res.data.author,
          description: res.data.description,
          published_date: res.data.published_date,
          publisher: res.data.publisher
        })
      })
      .catch(err => {
        console.log("Error from UpdateBookInfo");
      })
  };

  onChange = e => {
    this.setState({ [e.target.name]: e.target.value });
  };

  onSubmit = e => {
    e.preventDefault();

    const data = {
      title: this.state.title,
      isbn: this.state.isbn,
      author: this.state.author,
      description: this.state.description,
      published_date: this.state.published_date,
      publisher: this.state.publisher
    };

    axios
      .put('http://localhost:8082/api/books/'+this.props.match.params.id, data)
      .then(res => {
        this.props.history.push('/show-book/'+this.props.match.params.id);
      })
      .catch(err => {
        console.log("Error in UpdateBookInfo!");
      })
  };


  render() {
    return (
      <div className="UpdateBookInfo">
        <div className="container">
          <div className="row">
            <div className="col-md-8 m-auto">
              <br />
              <Link to="/" className="btn btn-outline-warning float-left">
                  Show BooK List
              </Link>
            </div>
            <div className="col-md-8 m-auto">
              <h1 className="display-4 text-center">Edit Book</h1>
              <p className="lead text-center">
                  Update Book's Info
              </p>
            </div>
          </div>

          <div className="col-md-8 m-auto">
          <form noValidate onSubmit={this.onSubmit}>
            <div className='form-group'>
              <label htmlFor="title">Title</label>
              <input
                type='text'
                placeholder='Title of the Book'
                name='title'
                className='form-control'
                value={this.state.title}
                onChange={this.onChange}
              />
            </div>
            <br />

            <div className='form-group'>
            <label htmlFor="isbn">ISBN</label>
              <input
                type='text'
                placeholder='ISBN'
                name='isbn'
                className='form-control'
                value={this.state.isbn}
                onChange={this.onChange}
              />
            </div>

            <div className='form-group'>
            <label htmlFor="author">Author</label>
              <input
                type='text'
                placeholder='Author'
                name='author'
                className='form-control'
                value={this.state.author}
                onChange={this.onChange}
              />
            </div>

            <div className='form-group'>
            <label htmlFor="description">Description</label>
              <input
                type='text'
                placeholder='Describe this book'
                name='description'
                className='form-control'
                value={this.state.description}
                onChange={this.onChange}
              />
            </div>

            <div className='form-group'>
            <label htmlFor="published_date">Published Date</label>
              <input
                type='date'
                placeholder='published_date'
                name='published_date'
                className='form-control'
                value={this.state.published_date}
                onChange={this.onChange}
              />
            </div>
            <div className='form-group'>
            <label htmlFor="publisher">Publisher</label>
              <input
                type='text'
                placeholder='Publisher of this Book'
                name='publisher'
                className='form-control'
                value={this.state.publisher}
                onChange={this.onChange}
              />
            </div>

            <button type="submit" className="btn btn-outline-info btn-lg btn-block">Update Book</button>
            </form>
          </div>

        </div>
      </div>
    );
  }
}

export default UpdateBookInfo;

Connecting the frontend to the backend

We just implemented all of our components! Now we need a little change in our server-side (back-end) project.

Changes required on the backend

If we try to call our back-end API from the front-end part, it gets an error that says: “Access to XMLHttpRequest at ‘http://localhost:8082/api/books&#8217; from origin ‘http://localhost:3000&#8217; has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.”

To solve this, we need to install cors in our back-end (server-side) project. Go to the project folder (e.g., MERN_A_to_Z) and run:

$ npm install cors

Now, update app.js (the back end’s entry point) with the following code:

// app.js

const express = require('express');
const connectDB = require('./config/db');
var cors = require('cors');

// routes
const books = require('./routes/api/books');

const app = express();

// Connect Database
connectDB();

// cors
app.use(cors({ origin: true, credentials: true }));

// Init Middleware
app.use(express.json({ extended: false }));

app.get('/', (req, res) => res.send('Hello world!'));

// use Routes
app.use('/api/books', books);

const port = process.env.PORT || 8082;

app.listen(port, () => console.log(`Server running on port ${port}`));

Running the frontend and backend

Follow the steps below to run both the frontend and backend of our MERN stack example.

Run the server

Now, run the server (inside the project folder):

$ npm run app

If you get any error, then follow the commands below (inside the project folder):

$ npm install
$ npm run app

Run the client

From the front-end project directory, run the command below:

$ npm start

If you get an error, again, follow the same commands below:

$ npm install
$ npm start

Testing our MERN stack app in the browser

Let’s check everything in the browser. Open http://localhost:3000 in your browser. Now you can add a book, delete a book, show the list of books, and edit books. The following routes should perform accordingly:

Add a new book: http://localhost:3000/create-book

The Add Book Page

Show the list of books: http://localhost:3000/

The Books List Page

Show any book’s info: http://localhost:3000/show-book/:id

Show Book Details Page

Update a book’s info: http://localhost:3000/edit-book/:id

The Edit Book Page

Congratulations! You have successfully completed this MERN stack tutorial.

You can visit my GitHub to see both the server-side and client-side portions of this MERN stack tutorial. You can also find the complete repo for our MERN stack example app on GitHub.

#mern #mongodb #expressjs #node #react 

Learn the MERN Stack: Build a Simple CRUD App from Scratch
Code  JS

Code JS

1662953444

Build an E-Commerce App with the MERN Stack Including Stripe & SockeIO

In this video, learn how to build an e-commerce app with the MERN stack including Stripe and SocketIO.

MERN stack is a web development framework. It consists of MongoDB, ExpressJS, ReactJS, and NodeJS as its working components. Here are the details of what each of these components is used for in developing a web application when using MERN stack:

  • MongoDB: A document-oriented, No-SQL database used to store the application data.
  • NodeJS: The JavaScript runtime environment. It is used to run JavaScript on a machine rather than in a browser.
  • ExpressJS: A framework layered on top of NodeJS, used to build the backend of a site using NodeJS functions and structures. Since NodeJS was not developed to make websites but rather run JavaScript on a machine, ExpressJS was developed.
  • ReactJS: A library created by Facebook. It is used to build UI components that create the user interface of the single page web application.

 

Github links: 
https://github.com/learnthiscode/ecomern-frontend  (Frontend) 
https://github.com/learnthiscode/ecomern-backend  (Backend)

Subscribe: https://www.youtube.com/channel/UCnmps10SDggjryJ3e4KzKFQ/featured 

#mernstack, #mern, #ecommerce

Build an E-Commerce App with the MERN Stack Including Stripe & SockeIO
Code  JS

Code JS

1662866893

How To Reset Password In Mern Stack | Send Reset Password Link Using Nodemailer

Forgot Password and Reset Password IN MERN Stack,Send Reset Password Link Using Nodemailer

In This Video We Will See How To Reset Password In Mern Stack. We Will See How To Send Reset Password Link Using Nodemailer.

MERN stands for MongoDB, Express, React, Node, after the four key technologies that make up the stack.

  • MongoDB — document database
  • Express(.js) — Node.js web framework
  • React(.js) — a client-side JavaScript framework
  • Node(.js) — the premier JavaScript web server
     

Express and Node make up the middle (application) tier. Express.js is a server-side web framework, and Node.js is the popular and powerful JavaScript server platform. Regardless of which variant you choose, ME(RVA)N is the ideal approach to working with JavaScript and JSON, all the way through.

Frontend - React.JS
Backend - Node.JS & Express.JS
Database - MongoDB, MongoDB Atlas
Authentication :- JWT Authentication
IDE used - Visual Studio Code

Source Code :- https://github.com/harsh17112000/MERN_forgot_password 

Subscribe: https://www.youtube.com/c/HarshPathakNV/featured 

#react #nodejs #mern #expressjs

How To Reset Password In Mern Stack | Send Reset Password Link Using Nodemailer
Code  JS

Code JS

1661758717

MERN Stack | Build a Food Ordering App using MERN Stack

In this tutorial, we build a food ordering app using MERN Stack.

Topics covered in the video:

1. State management using Redux (redux-thunk & new redux dev tools)
2. Creating custom hooks & re-usable components
3. Setting up router and pages
4. Setting up express server
5. Creating models & queries using mongoose
6. Creating a MongoDB Database
7. Generating dummy data using Faker-js
8. Implementing Authentication
9. Integrating Payments using Stripe

0:00 Demo
3:08 Creating React App
3:45 Installing Modules
6:26 Building the first component
12:00 Navigation 
21:00 Homepage
38:08 Setting up server
1:06:35 Displaying Products
1:23:32 Redux
1:55:19 Menu
2:36:24 Checkout
3:40:28 Payments
4:16:37 Firebase Authentication
4:55:10 Thanks for watching!:)

GitHub URL:https://github.com/judygab/web-dev-projects/tree/main/food-ordering-app 

Subscribe : https://www.youtube.com/channel/UCObrjoZZJSjznfCO5Vx9qUQ/featured 

#mern #nodejs #react #javascript 

MERN Stack | Build a Food Ordering App using MERN Stack
Garry Taylor

Garry Taylor

1661415212

MERN Authentication: Authentication with JWT in MERN Stack

This MERN Authentication tutorial shows how to implement authentication (using JSON web tokens), within the MERN stack

  1. MERN Authentication Tutorial #1 - Intro & Starter Project
  2. MERN Authentication Tutorial #2 - User Routes, Controller & Model
  3. MERN Authentication Tutorial #3 - Signing Up & Hashing Passwords
  4. MERN Authentication Tutorial #4 - Email & Password Validation
  5. MERN Authentication Tutorial #5 - JSON Web Tokens (theory)
  6. MERN Authentication Tutorial #6 - Signing Tokens
  7. MERN Authentication Tutorial #7 - Logging Users In
  8. MERN Authentication Tutorial #8 - React Auth Context
  9. MERN Authentication Tutorial #9 - Login & Signup Forms
  10. MERN Authentication Tutorial #10 - Making a useSignup Hook
  11. MERN Authentication Tutorial #11 - Making a useLogout Hook
  12. MERN Authentication Tutorial #12 - Making a useLogin Hook
  13. MERN Authentication Tutorial #13 - Setting the Initial Auth Status
  14. MERN Authentication Tutorial #14 - Protecting API Routes
  15. MERN Authentication Tutorial #15 - Making Authorized Requests
  16. MERN Authentication Tutorial #16 - Protecting React Routes
  17. MERN Authentication Tutorial #17 - Assigning Workouts to Users

MERN Authentication Tutorial #1 - Intro & Starter Project

MERN Authentication Tutorial #2 - User Routes, Controller & Model

In this MERN auth tutorial, you'll make a user controller & model, and set up some routes for authentication.

 

MERN Authentication Tutorial #3 - Signing Up & Hashing Passwords

MERN Authentication Tutorial #4 - Email & Password Validation

MERN Authentication Tutorial #5 - JSON Web Tokens (theory)

In this MERN Authentication tutorial you'll learn about JSON Web Tokens (JWT's) and how they work under the hood when it comes to authentication.

MERN Authentication Tutorial #6 - Signing Tokens

In this MERN Authentication tutorial, we'll see how to sign tokens and send them back to the client.

MERN Authentication Tutorial #7 - Logging Users In

MERN Authentication Tutorial #8 - React Auth Context

MERN Authentication Tutorial #9 - Login & Signup Forms

In this MERN auth tutorial, we'll flesh out the login and signup forms.

MERN Authentication Tutorial #10 - Making a useSignup Hook

In this MERN auth lesson, you'll create a custom, reusable React hook that we can use to sign new users up to the application.

MERN Authentication Tutorial #11 - Making a useLogout Hook

In this MERN auth tutorial, we'll make a custom useLogout hook to log users out of the application.

MERN Authentication Tutorial #12 - Making a useLogin Hook

In this MERN auth tutorial, we'll make a custom useLogin hook to log users in to the application.

MERN Authentication Tutorial #13 - Setting the Initial Auth Status

MERN Authentication Tutorial #14 - Protecting API Routes

Hey gang, in this MERN auth tutorial, you'll learn how to protect certain API routes from unauthenticated users.

MERN Authentication Tutorial #15 - Making Authorized Requests

MERN Authentication Tutorial #16 - Protecting React Routes

In this MERN auth tutorial we'll protect some of the React routes from users that are not authenticated.

MERN Authentication Tutorial #17 - Assigning Workouts to Users

 

🐱‍💻 Access the course files on GitHub:
https://github.com/iamshaunjp/MERN-Auth-Tutorial

#mern #mongodb #expressjs #node #react #security 

 

MERN Authentication: Authentication with JWT in MERN Stack
Code  JS

Code JS

1661013702

Uploading Images with Mern Stack ( ReactJs, Nodejs, ExpressJs, Mongodb )

In This Video We Will Create Image Uploading With Mern Stack. We Will use Multer For Image Uploading.@Harsh Pathak

Frontend - React.JS, & React Bootstrap
Backend - Node.JS & Express.JS , multer
Database - MongoDB , MongoDB Atlas
IDE used - Visual Studio Code

Timestamp
0:00 - intro
00:40 - demo 
05:10 - create react app
06:46 - create server part
34:16 - install react-router-dom
01:00:15 - create database
01:01:00 - install mongoose
01:02:01 - create mogodb atlas setup
01:13:00 - create usersSchema
01:16:08 - create model
01:22:57 - install multer
02:10:28 - create get user api
02:27:37 - create delete user api
02:42:38 - outro

Source code :- https://github.com/harsh17112000/mern_imgupload_youtube 

Subscribe : https://www.youtube.com/c/HarshPathakNV/featured 

#mern #react #nodejs #mongodb 

Uploading Images with Mern Stack ( ReactJs, Nodejs, ExpressJs, Mongodb )
Edward Jackson

Edward Jackson

1660015483

MERN Stack Project: Create a Task Management System | Todo App

In this MERN stack project tutorial for beginners, you'll learn how to create a task management system with MERN Stack. Learn a lots of things like how to create relations in mongoDb, create authentications, create private routes, custom react.js hooks and many more.

Today we are going to create a task management system using MERN stack. Where user can create their own account and manage their tasks. This will be simple app for MERN beginners. In this video we will learn a lots of things like how to create relations in mongoDb, create authentications, create private routes, custom react.js hooks and many more. I hope you guys will like it.

⏲Timestamps -
00:00:00 - Intro
00:05:22 - Backend Init
00:12:17 - Express.js Setup
00:14:54 - MongoDB Setup
00:26:14 - Express.js Middleware
00:28:24 - Express.js Routes
00:38:07 - Auth Routes
01:09:19 - Error Handling
01:22:00 - Auth Routes (logout & is_logged_in)
01:28:18 - Users Routes
01:41:17 - Tasks Routes
02:09:49 - Frontend Init
02:17:54 - React Routes
02:21:44 - Private Routes
02:30:03 - Vite.js Server Proxy
02:32:45 - Page Layout
02:35:02 - Auth Page
03:00:00 - Home Page
03:00:58 - Nav (Home Page)
03:12:37 - Tasks (Task List & Task Item)
03:47:31 - Edit Profile Page
04:03:03 - Quick Fix 01
04:06:17 - Quick Fix 02
04:07:54 - bye bye

👉 Source Code: https://github.com/ShaifArfan/mern-task-management-tool/tree/youtube-tutorial 

#mern #mongodb #react #node #express 

MERN Stack Project: Create a Task Management System | Todo App