2024
MERN Stack
Application
Development
© Edunet Foundation. All rights reserved.
Chapter 1: Getting Familiar with Full-Stack Web
Development
Learning Outcomes:
Gain a comprehensive understanding of web application
architecture.
Learn the components and functionality of the MERN stack
(MongoDB, Express.js, React, Node.js).
Develop skills in setting up and configuring a local development
environment.
Acquire proficiency in using Visual Studio Code (VSCode) and
Git.
Enhance knowledge of HTML and CSS.
1.1 Overview and architecture of web development
1.1.1 What is a Web Application
A web application is a type of software that you can access using a web browser over
the internet. Unlike traditional software that you need to install on your computer, web
applications run on web servers. You interact with them through your browser by going
to a specific URL. Examples include online banking systems, email services like Gmail,
and social media platforms like Facebook.
Terminologies:
1. Web: The World Wide Web (WWW), or simply the Web, is a system of
interlinked hypertext documents and multimedia content that can be accessed
via the internet. It allows users to view and navigate web pages through web
browsers.
2. Web Page: A web page is a single document on the web, typically written in
HTML (HyperText Markup Language). It can contain text, images, videos, links,
and other multimedia elements. An example of a web page is a single article
on a news website.
3. Website: A website is a collection of related web pages hosted under a single
domain name. Websites provide various types of content and services to users.
For example, www.example.com could be a website containing multiple pages
like a homepage, about page, contact page, and blog.
© Edunet Foundation. All rights reserved. | 1
4. Web Browser: A web browser is a software application used to access and
view web pages on the internet. Popular web browsers include Google Chrome,
Mozilla Firefox, Microsoft Edge, and Safari.
5. URL (Uniform Resource Locator): A URL is the address of a web page on
the internet. It specifies the location of the web page and how to retrieve it. For
example, https://www.example.com/page1 is a URL.
6. HTML (HyperText Markup Language): HTML is the standard language used
to create web pages. It describes the structure of web pages using elements
and tags.
7. CSS (Cascading Style Sheets): CSS is a stylesheet language used to
describe the presentation and layout of web pages. It controls the visual
appearance of HTML elements.
8. JavaScript: JavaScript is a programming language used to create interactive
effects and dynamic content on web pages. It allows for client-side scripting to
enhance user experiences.
9. Domain Name: A domain name is the human-readable address of a website,
such as www.example.com. It is used to identify and access websites on the
internet.
10. Web Server: A web server is a computer system that hosts websites and
serves web pages to users upon request. It handles incoming requests from
web browsers and delivers the appropriate content.
11. HTTP/HTTPS (HyperText Transfer Protocol/Secure): HTTP is the protocol
used for transferring web pages over the internet. HTTPS is the secure version
of HTTP, which encrypts data for secure communication.
12. IP Address: An IP address is a unique numerical identifier assigned to each
device connected to the internet. It allows devices to communicate with each
other.
13. Content Management System (CMS): A CMS is a software platform that
allows users to create, manage, and modify web content without needing to
write code. Examples include WordPress, Joomla, and Drupal.
14. Responsive Design: Responsive design refers to the practice of creating web
pages that adjust and optimize their layout for different screen sizes and
devices, such as desktops, tablets, and smartphones.
15. SEO (Search Engine Optimization): SEO is the process of optimizing a
website to improve its visibility and ranking in search engine results. This
involves using keywords, meta tags, and other techniques to attract more
organic traffic.
© Edunet Foundation. All rights reserved. | 2
Difference Between Website and Web Application:
Figure 1. -Web Application Vs A Website
Images Source: https://www.geeksforgeeks.org/difference-between-web-application- and-website/
Web Application Website
Web application is designed for Website basically contains static
interaction with end users. content.
The user of web application can read the The user of website only can read
content of web application and also the content of website but not
manipulate the data. manipulate .
The web application site should be The website does not need to be
precompiled before deployment. precompiled .
The function of a web application is quite
The function of website is simple.
complex.
Web site is not interactive for
Web application is interactive for users.
users.
The browser capabilities involved with a The browser capabilities involved
web application is high. with web site is high.
Integration is complex for web application
Integration is simpler for web site.
because of its complex functionality.
© Edunet Foundation. All rights reserved. | 3
Web application mostly requires In web site authentication is not
authentication necessary.
EXAMPLE :- Breaking News, Aktu
EXAMPLE :- Amazon, Facebook, etc.
website, etc.
Need for Web Applications: Web applications are crucial because they offer
several benefits:
1. Accessibility: You can access them from any device with an internet
connection and a web browser, without needing to install anything.
2. Interactivity: They provide a dynamic and interactive user experience,
allowing for real-time data processing and feedback.
3. Convenience: They support various business functions, like online
transactions, customer service, and data management, making processes
more efficient.
4. Cross-Platform: They work across different operating systems and devices,
ensuring a consistent experience for all users.
5. Scalability: They can be easily updated and maintained from a central server,
which simplifies the process of delivering new features and improvements.
1.1.2 Web Development Life Cycle:
The software and web development life cycle adheres to a specific standard that has
to be followed to move in the right direction. There are frameworks, methodologies,
modelling tools, and languages involved.
The Web Development Life Cycle is a method that outlines the stages involved in
building websites and web applications, whether it is javascript development, python
development, or ASP .Net Development. It provides a structured approach, ensuring
optimal results throughout the development process. DLC is a structured approach to
software development that includes several phases:
The 7 Stages of The Web Development Life Cycle –
1. Gathering Relevant Information
2. Planning - Sitemap and Wireframe
3. Design & Layout
4. Content Creation
5. Development
6. Testing, Review, and Launch
7. Maintenance and Updation
© Edunet Foundation. All rights reserved. | 4
Figure 2. Web Development Life Cycle
Images Source: https://www.signitysolutions.com/blog/web-development-life-cycle
Let's discuss the web development life cycle stages one by one:
Gathering Relevant Information:
The first stage is the most important in understanding the life cycle approach of website
development as it involves learning about the client's requirements. Identify their needs
and help them by providing the perfect solution. Have a clear idea about the target
audience. What the business goals are, and how the website will be utilized to
accomplish those objectives?
Here are the considerations:
Purpose:
1. What is the purpose of the website that the developer will be building?
2. What is the actual plan: to provide information solely and sell a product
or service?
Objectives:
1. What is the main goal of building the website?
2. Whether it is informational or promotional?
Target Audience:
Is there a specific group of people that will help in accomplishing yourobjectives?
During the website design and development process, it is important to visualize what
type of people you would like to visit the website. Consider their age, gender, likes, and
dislikes. This will certainly help in designing the best website according to their interest.
Content:
1. What type of content do you post on the site?
2. Is the audience looking for a specific type of information?
3. Are they looking for promotions, deals, or offers to avail?
© Edunet Foundation. All rights reserved. | 5
The news portal is different from an entertainment site, and online sites for teenagers
are different from adults.
Every website is different from the other, so gathering relevant information regarding the
project is very important. So, it is vital to get insights so that an aesthetically appealing
website is created.
2) Planning - Sitemap and Wireframe
With all the information that has been gathered from stage one, the design and
implementation strategies are planned according to the type of website and target
audience.
A site map is created in this phase.
For building a full-fledged website having impeccable features and functionalities, it is
important to plan wisely. There has to be a detailed list of all the areas of the website
and the sub-topics. This is a guide that describes what content will be there on the site,
and there is an easy-to-understand navigational system.
Think of the best user interface that is created for easy navigation. The wireframes give
an outline of the pages of the website.
Take the help of tools for creating the wireframe. All the planning processes should have
the involvement of the client. So, the client has an idea about the blueprint of the project.
3) Design & Layout
Next is to determine the look and feel of the website. In the design phase, it is essential
to embed elements like the logo of the company and the colours that help to enhance to
the identification of the company on the website.
The designer gives life to the graphics, typography, colours, animations, buttons, drop-
down and pop-up menus, and more as per the project requirement.
It is the responsibility of the web designer to create one or more than one prototype for
the website. This is basically a jpeg image of the final design. Designers give companies
access to the workflow so that they can view the progress of the development.
Meeting the demand of the audience with the help of web design is also crucial. If the
design is mundane, the website will not be able to capture the user's attention, and
this will increase the bounce rate. The elements should reflect the brand image as
well as the business vision.
According to recent research, 75% of users make judgments about a company's
credibility based on their website design.
Therefore, it's not just about having a functional website but also creating an exceptional
© Edunet Foundation. All rights reserved. | 6
user experience that fosters trust and engagement.
4) Content Creation
No matter how visually appealing your website may be, effective communication with
your customers is indispensable.
The primary objective of content creation is to establish a communication channel
through the user interface. It involves presenting relevant information about your
company in an engaging and easily comprehensible manner.
This encompasses the inclusion of:
Compelling calls-to-action
Crafting creative headlines
Formatting the content for readability
Performing line editing
Updating the texts throughout the entire web development process.
The content creation stage plays a pivotal role in shaping the branding and marketing
of your website or web application. It serves as a platform to define the purpose and
objectives of your online presence through impactful and persuasive writing.
5) Development
The development is a stage where the website is built while maintaining the essence of
the website's purpose. All the graphic elements are taken into consideration and are
used to generate a functional website.
The process begins with first developing the home page, followed by the interior pages.
The main focus is given to the navigational structure of the site. Content Management
System, interactive contact us forms, and shopping carts are made functional in this
development step. The web design & development company suggests changes that are
done after consideration.
Do you know that a successful website needs an understanding of front-end website
development and back-end development? This means valid HTML/CSS codes are
compiled as per the web standards to enhance the functionality for a larger audience.
6) Testing, Review, and Launch
After the completion of web development, it is tested. The functionality is tested along
with the device compatibility.
The web designer should be well-versed with the current trends and standards so that
the design and development are done accordingly. The technologies used are HTML
and CSS. The tester validates the codes written for the website.
When the designer is given the final approval, the website is ready for delivery. The
quality assurance team tests for functionality, compatibility, and performance to ensure
© Edunet Foundation. All rights reserved. | 7
that the website is ready for launch.
Other testing includes integration testing, stress testing, scalability, load testing,
resolution testing, and cross-browser compatibility. Once the green flag is shown, it is
deployed to the server using FTP.
7) Maintenance and Updation
The web development stages don't end after deployment. There are many post-
deployment tasks that take place. Some elements are changed as per the user's
feedback, support, and maintenance.
One good way to grab potential visitors and repeat their visits is to keep updating the
content and adding new products on a regular basis. The website drives by CMS allows
the customer to edit the content.
1.1.3 Web Development Models
There are various Web development life cycle models defined and designed which are
followed during the software development process. These models are alsoreferred to as
Software Development Process Models". Each process model followsa Series of steps
unique to its type to ensure success in the process of software development. Following
are the most important and popular DLC models followed in the industry: Waterfall
Model, Iterative Model, Prototype Model, Spiral Model, and Agile Model. We will learn
each model in detail.
Waterfall Model:
The waterfall model is a continuous software development model in which
development is seen as flowing steadily downwards (like a waterfall) through the steps
of requirements analysis, design, implementation, testing (validation), integration, and
maintenance.
Linear ordering of activities has some significant consequences. First, to identify the
end of a phase and the beginning of the next, some certification techniques have to
be employed at the end of each step. Some verification and validation usually do this
mean that will ensure that the output of the stage is consistent with its input (which is
the output of the previous step) and that the output of the stage is consistent with the
overall requirements of the system.
© Edunet Foundation. All rights reserved. | 8
Figure 3. Water Fall Model
Images Source: https://www.javatpoint.com/software-engineering-software-development-life-cycle
Advantages:
Before the next phase of development, each phase must be completed.
Suited for smaller Projects where requirements are well-defined.
Disadvantages:
An error can be fixed only during the phase.
The testing period comes quite late in the developmental process.
Iterative Model:
© Edunet Foundation. All rights reserved. | 9
It is a particular implementation of a development life cycle that focuses on an initial,
simplified implementation, which then progressively gains more complexity and a
broader feature set until the final system is complete. In short, iterative development
is a way of breaking down the software development of a large application into smaller
pieces.
Advantages:
Figure 4. Iterative Model
Images Source: https://www.javatpoint.com/software-engineering-software-development-
life-cycle
Some working functionality can be developed early in the development life cycle
(DLC).
It is easily adaptable to the ever-changing needs of the project as well as the
client.
It is best suited for agile organizations.
It is more cost-effective to change the scope or requirements in Iterative model.
Parallel development can be planned.
Disadvantages:
More resources may be required.
Although cost of change is lesser, but it is not very suitable for changing
requirements.
More management attention is required.
It is not suitable for smaller projects.
Highly skilled resources are required for skill analysis.
© Edunet Foundation. All rights reserved. | 10
Prototype Model:
The prototyping model starts with requirements gathering. The developer and the user
meet and define the purpose of the software, identify the needs, etc.
A 'quick design' is then created. This design focuses on those aspects of thesoftware
that will be visible to the user. It then leads to the development of a prototype. The
customer then checks the prototype, and any modifications or changes that are
needed are made to the prototype.
Looping takes place in this step, and better versions of the prototype are created.
These are continuously shown to the user so that any new changes can be updated
in the prototype. This process continues until the customer is satisfied with the system.
Once a user is satisfied, the prototype is converted to the actual system with all
considerations for quality and security.
Figure 5. Prototype Model
Images Source: https://www.geeksforgeeks.org/advantages-and-disadvantages-of-prototype-model/
Advantages:
This model is flexible in design.
It is easy to detect errors.
We can find missing functionality easily.
There is scope for refinement, which means new requirements can be easily
accommodated.
It can be reused by the developer for more complicated projects in thefuture.
Disadvantages:
This model is costly.
It has poor documentation because of continuously changing customer
requirements.
There may be too much variation in requirements.
Customers sometimes demand the actual product to be delivered soon after
seeing an early prototype.
© Edunet Foundation. All rights reserved. | 11
Spiral Model:
The spiral model is a risk-driven process model. This DLC model helps the group to
adopt elements of one or more process models like a waterfall, incremental, waterfall,
etc. The spiral technique is a combination of rapid prototyping and concurrency in
design and development activities.
Each cycle in the spiral begins with the identification of objectives for that cycle, the
different alternatives that are possible for achieving the goals, in addition, the
constraints that exist. This is the first quadrant of the cycle (upper-left quadrant).
The next step in the cycle is to evaluate these different alternatives based on the
objectives and constraints. The focus of evaluation in this step is based on the risk
perception for the project.
The next step is to develop strategies that solve uncertainties and risks. This step may
involve activities such as benchmarking, simulation, and prototyping.
Figure 6. Spiral Model
Images Source: https://www.geeksforgeeks.org/advantages-and-disadvantages-of-prototype-model/
Advantages:
Software is produced early in the software life cycle.
Risk handling is one of the important advantages of the Spiral model, it is the
best development model to follow due to the risk analysis and risk handling at
every phase.
© Edunet Foundation. All rights reserved. | 12
Flexibility in requirements. In this model, we can easily change requirements at
later phases and can be incorporated accurately. Also, additional Functionality
can be added at a later date.
Disadvantages:
It is not suitable for small projects as it is expensive.
It is much more complex than other DLC models. The process is complex.
Too much dependable on Risk Analysis and requires highly specific expertise.
Difficulty in time management. As the number of phases is unknown at the start of
the project, so time estimation is very difficult.
Agile Model:
Agile methodology is a practice that promotes continuous interaction of development
and testing during the DLC process of any project. The Agile method divides the entire
project into small incremental builds. All of these builds are provided in iterations, and
each iteration lasts from one to three weeks.
Any agile software phase is characterized in a manner that addresses several key
assumptions about the bulk of software projects:
It is difficult to think in advance about which software requirements will persist and
which will change. It is equally difficult to predict how user priorities will change as the
project proceeds.
For many types of software, design, and development are interleaved. Both activities
should be performed in tandem so that design models are proven as they are created.
It is difficult to think about how much design is necessary before construction is used
to test the configuration.
Analysis, design, development, and testing are not as predictable (from a planning
point of view) as we might like.
© Edunet Foundation. All rights reserved. | 13
Figure 7. Agile Model
Images Source:
Advantages:
Customer satisfaction by rapid, continuous delivery of useful software.
People and interactions are emphasized rather than processes and tools.
Customers, developers, and testers constantly interact with each other.
Working software is delivered frequently (weeks rather than months).
Disadvantages:
In the case of some software deliverables, especially large ones, assessing the
effort required at the beginning of the development life cycle is difficult.
There is a lack of emphasis on necessary designing and documentation.
The project can easily get taken off track if the customer representative is
unclear about what final outcome they want.
1.1.4 Web application architecture
© Edunet Foundation. All rights reserved. | 14
What is web application architecture?
Figure 8. Web application architecture
Images Source: https://acropolium.com/blog/modern-web-app-architecture/
Web system architecture is a framework for relationships between a web application’s
client-side (frontend) and server-side (backend) components. Simply put, architecture
outlines how the elements of an app work together.
Let’s take a brief detour to lay out the basic terms. A web application is software
accessible through a web browser. Unlike a website (a collection of static pages
withtext, images, audio, and video), a web app allows users to interact with its
elements and manipulate content without reloading the page.
Here are some well-known examples of web apps:
Dynamic: Hubspot, Netflix, Facebook
E-commerce: eBay, Amazon, Walmart
CMS: Joomla, Drupal, WordPress
SPA (single page apps): Pinterest, Gmail, PayPal
PWA (progressive web apps): Forbes, Spotify, Starbucks
Before discussing how important web app architecture is for development, we should
explain what’s under the hood of a web application.
Components of web application architecture infrastructure
© Edunet Foundation. All rights reserved. | 15
Figure 9. Web application Components
Images Source: https://acropolium.com/blog/modern-web-app-architecture/
The main components of web portal architecture include a browser, web application
server, and database server. Let’s overview each element and see how they impact
the system’s performance, scalability, and reliability.
UI:
Web UI architecture is a visual presentation of a web app shown in a web browser and
allows users to interact with it. It’s rare to find UI as part of the architecture, but it is a
component in modern apps. Why so? Quite often, some parts of the business logic
work in the browser via JavaScript.
The content of the web page works through:
HTML (HyperText Markup Language) defines the content and structure of the
webpage.
CSS (Cascading Style Sheets) specifies the styling (text size, color, and font)
and presentation of the page (separates the content and layout).
JavaScript is a programming language responsible for browser interactions.
The JavaScript layer rests in the user’s browser and communicates with the backend
to update the webpage in real time. Modern website architecture models allow the
page content to change dynamically as users interact with the interface elements.
Web Browser
© Edunet Foundation. All rights reserved. | 16
Web browsers are the primary interface between end-users and web applications that
people run on their devices, such as laptops, smartphones, or tablets. They are written
in HTML, CSS, and JavaScript.
Web browsers let users interact with the software by clicking buttons, filling out forms,
and navigating through pages. Also, they ensure compatibility across multiple devices
and browsers, impact user experience, and play a crucial role in web application
security.
Web app server
Web servers are computers that accept requests, process them, and send the data
to the user’s browser.
The term “server” applies to any computer that provides services over the internet (or
private network). Servers fall into different categories based on the type of services
that run on them. For instance, web servers process HTTP (port 80) and HTTPS
(port 443) requests.
Database server
These are centralized locations for databases (organized collections of information).
Such servers communicate with web ones and provide data to authorized users.
Application server
An application server is a program that runs on the server side. It provides a web
application’s business logic and functionality by receiving requests from the client side,
processing them, and sending back the response.
Application servers improve web app security by enforcing authentication,
authorization, and encryption. By distributing the processing load across multiple
servers, you can improve app scalability and performance.
DNS
The domain name system (DNS) is an internet-based hierarchical naming system that
translates a domain name (like www.google.com) into an IP address (8.8.8.8).
Browsers need IP addresses to communicate with web servers. DNS simply helps
users connect using readable names instead of complex numbers. You can think of
DNS as the contact directory for the internet.
Messaging middleware
Web applications can consist of multiple services hosted across several servers.
Messaging middleware helps different software modules, programming languages,
and applications communicate.
The client-side and server-side of the web app interact using synchronous (HTTPS
and TCP) protocols. Server-side components of the app could also use asynchronous
(AMQP) communication protocol. Besides, middleware software and application
© Edunet Foundation. All rights reserved. | 17
programming interfaces (APIs) bridges data between applications and servers.
Load balancer
Every server has limited RAM and CPU, so more user traffic can result in performance
issues. Here, load balancers come in handy.
A load balancer processes traffic and distributes it across web servers based on the
available computational resources. This optimizes the load, allowing the web app to
run smoothly.
Caching
The cache is a temporary medium that stores web page data and delivers it faster
upon repeated requests.
In the web app server architecture, caching usually happens in the browser. For
instance, when you first load a web page, parts of it are saved in your local storage.
Then, when you reload the page, the browser gets these files directly from the cache
(without contacting the web server).
CDN
The content delivery network (CDN) is a server node system that stores and delivers
static content (images, audio, videos, CSS, and JavaScript files). CDNs can improve
the latency for users who live far away from data centers where your web app is
hosted.
Imagine a user from California accessing a web app in a data center in New York. The
browser can fetch information from the data center, but the page will take longer to load
because of the distance. Now, let’s say a web app utilizes a CDN in California. Then,
the browser can download heavy files from a nearby node much faster.
Firewall
A firewall is a network security system that monitors and controls incoming and
outgoing traffic based on predefined rules. It acts as a barrier between the internet and
the internal network, preventing unauthorized access and blocking potentially harmful
traffic to protect sensitive data.
Compliance with regulatory standards is mandatory in many business sectors, such
as finance and healthcare. By enforcing security policies, firewalls can help web
applications meet industry-specific requirements.
So, it’s time to tell you how all these components work together when someone
interacts with a web app.
How modern web applications work
Now that you’re familiar with the terms, we can show you what happens when a user
enters a URL in the address bar.
1. The client (browser) contacts a DNS server, which provides the IP address.
2. The browser then sends a request for web documents (JSON, HTML, and
© Edunet Foundation. All rights reserved. | 18
others) to the web server.
3. The web server forwards the requests to the application logic (business layer
of the app), which determines the course of action depending on the user’s
access level and type of request.
4. If the request meets the access criteria, the app logic loads data from the
database and sends them to the browser.
5. The browser receives a web document with data, parses it, and loads any static
files (JavaScript, CSS, images, video, etc.) from the CDN.
6. In modern web applications, the app logic may have the JavaScript layer, which
then communicates with the backend and different APIs from the browser.
7. The browser renders the information and displays it as a website page.
All these processes take place on different layers (tiers) of the web application. And
this brings us to the next topic.
Layers of web application architecture
Figure 10. Web application Layers
Images Source: https://acropolium.com/blog/modern-web-app-architecture/
The infrastructure of a web app includes the presentation, business, data access, and
database layers. Here’s what they are responsible for.
Presentation layer
The presentation level is the frontend of the web application located in your browser.
This tier renders data from the backend into readable content and interface elements.
When a user interacts with a web interface, the presentation layer sends a request to
the business layer.
© Edunet Foundation. All rights reserved. | 19
Business layer
The business layer (application logic tier) is the backend part that determines the
internal logic and rules. It contains the application code that coordinates all processes
in the app. This tier also transfers the data between the presentation and persistence
layers.
Data access layer
This layer interacts with the database to store and retrieve data and operate with it.
Besides, it includes the persistence layer, which sends data to the business one
upon request.
Database layer
The database layer comprises a database management system (DBMS) and its actual
storage. Consider its design and implementation to ensure the application is fast,
reliable, and secure.
Here’s how the layers work together:
1. The user interacts with the presentation layer via a browser.
2. The presentation layer sends requests to the business logic tier.
3. The business logic tier communicates with the persistence tier, which includes
the database layer, to retrieve the necessary data.
4. The persistence layer retrieves the data from the database and sends it back
to the business logic tier.
5. The business logic tier processes and sends the data to the presentation
layer.
6. The presentation layer delivers the data to the user via a web browser.
At this point, you should already have a clear picture of the whole technology layout.
Time to figure out how to choose the architecture for your SaaS MVP.
© Edunet Foundation. All rights reserved. | 20
Types of web application architecture
Figure 11. Types of Web application
Images Source: https://acropolium.com/blog/modern-web-app-architecture/
Every application (web, desktop, or mobile app) has two sides: frontend and backend.
Frontend (client-side) — a code that runs in the user’s web browser or
interface. Users see and interact with it.
Backend (server-side) — servers, databases, and application logic that run
behind the curtain. Backend components store data, process requests, and
deliver the information you see in the app.
So, we’ll describe the common types of modern architectures separately for the
client and server sides of the app.
Frontend
Server-side rendered application (traditional)
In the server-side rendered (SSR) architecture, the web server generates the whole
page on every request. This means the browser must reload after every time there’s
a need to update the page. While it’s great when render times are low, the UX can
go south if it takes too long.
Single-page application
The single-page application (SPA) is a modern web application architecture that
serves web pages with dynamically updated content. Here’s how the process goes:
The web server generates a single page with minimal HTML data and a
JavaScript layer.
The JavaScript layer communicates with the backend to fetch the data and
© Edunet Foundation. All rights reserved. | 21
render the remaining HTML. It also provides real-time updates.
The SPA architecture allows the web app to dynamically rewrite the page content
without reloading the page. Because of that, the user experience becomes dynamic,
and requests become less resource-demanding for the backend.
Progressive web application
Progressive web application (PWA) architecture is a hybrid of SPAs and mobile apps.
In addition to dynamic JavaScript code, PWAs use:
Web manifests (JSON files with metadata)
Service workers (APIs that bridge app, browser, and network)
Service workers connect users to the backend and cache the app data in the
background, allowing the web app to be available even offline.
Backend
Microservices
Microservice architecture implies that the app’s backend is split up into multiple single-
purpose loosely coupled services. These services run separately,communicate
via a network, and scale independently. In addition, microservices communicate
synchronously (RESTful API, TCP) or asynchronously (messaging).
For example, an online shop may have microservices for customer registration, file
uploading, user interface, product catalog, cart, and payment process.
Here’s what makes the isolated structure of this architecture appealing:
Microservice can be built independently by different teams, improving the
development speed
The code or tech stack for each service can be changed without impacting the
whole app so that you can test different parts of the system
Services can be added to the app at any stage of the application’s life cycle
This web development architecture has some drawbacks, though. Resilience testing
and monitoring are challenging because you have to work with separate modules
across multiple servers. On top of that, your team has to document communications
between every microservice.
Serverless
Serverless architecture is a cloud infrastructure hosted by third-party providers, such
as Amazon Web Services (AWS), Microsoft Azure, and Google Cloud.
Serverless solutions can be an alternative or supplement to traditional enterprise
web application architecture, boasting several advantages:
The serverless provider takes care of the hardware and softwaremanagement,
allowing your team to focus on building and managing your application
© Edunet Foundation. All rights reserved. | 22
You can quickly scale the infrastructure up and down based on your needs
Most serverless plans have a flexible billing model, so you only pay for the
resources and storage you use
The infrastructure security and available resources depend on the third-party vendor,
which might concern some enterprises (FinTech and healthcare come to mind).
However, you can opt for advanced subscription plans and tenant isolation models
with advanced authentication and isolated databases.
Use Backend as a Service as a solution for microservice- and serverless-based web
applications. It allows developers to focus on the app frontend and business logic.
On the other hand, backend frameworks provide a set of pre-built components and
libraries, providing more flexibility and customization options.
1.2 Understanding the MERN Stack
One of the most popular stacks for web development is the MERN stack. This stack
offers a comprehensive framework for developers, where each component plays a
crucial role in building web applications. The MERN stack, a JavaScript-based
technology stack, is known for its ease of use and rapid deployment capabilities for
full-stack web applications. The stack consists of four core technologies: MongoDB,
Express.js, React.js, and Node.js, each contributing to a smoother and more efficient
development process.
MongoDB: A non-relational database that stores data in flexible, JSON-like
documents, allowing for easy scalability and management of large amounts of
data.
Express.js: A minimalist web application framework for Node.js that simplifies
the process of building robust web servers and APIs.
React.js: A powerful JavaScript library for building dynamic and interactive user
interfaces, particularly single-page applications where real-time updates are
crucial.
Node.js: A JavaScript runtime built on Chrome's V8 engine, enabling
developers to build scalable and high-performance web servers using
JavaScript.
© Edunet Foundation. All rights reserved. | 23
Figure 12.MERN stack layout
Images Source:
The MERN stack is designed to streamline the development process, making it more
straightforward and efficient for developers to create full-featured web applications.
Need for MERN Stack:
The MERN stack is a popular web development framework that combines four
powerful technologies: MongoDB, Express.js, React, and Node.js. Each component
plays a crucial role in building modern, dynamic web applications. Here are the
reasons why the MERN stack is widely used and beneficial:
1. Full-Stack JavaScript:
o The MERN stack uses JavaScript for both client-side and server-side
development. This unification simplifies the development process, as
developers can use a single language throughout the entire application,
leading to better consistency and code reusability.
2. Efficient Development:
o By using a single language and a set of well-integrated tools, the MERN
stack allows for faster development cycles. Developers can quickly
build, test, and deploy applications, which is especially beneficial in agile
development environments.
3. Component-Based Architecture:
o React, the front-end component of the MERN stack, promotes a
component-based architecture. This means developers can create
reusable UI components, leading to more maintainable and scalable
code. This approach also enhances the user experience by allowing for
dynamic and responsive interfaces.
© Edunet Foundation. All rights reserved. | 24
4. Scalability:
o MongoDB, a NoSQL database, is designed to handle large volumes of
data and can scale horizontally. Node.js, with its event-driven
architecture, can handle numerous simultaneous connections
efficiently. This makes the MERN stack suitable for applications that
need to scale and handle high traffic.
5. Performance:
o Node.js provides a non-blocking, asynchronous runtime environment,
which enhances the performance of the server-side logic. Combined
with MongoDB's efficient data storage and retrieval capabilities, the
MERN stack ensures that applications run smoothly and quickly.
6. Open Source and Community Support:
o All components of the MERN stack are open source, which means they
are free to use and have a large community of developers contributing
to their improvement. This extensive community support provides ample
resources, libraries, and tools, making development easier and more
efficient.
7. JSON Everywhere:
o JSON (JavaScript Object Notation) is used across the stack for data
interchange. MongoDB stores data in a JSON-like format, Node.js and
Express.js use JSON for handling HTTP requests, and React uses
JSON to manage component state. This consistency in data format
simplifies data handling and reduces the need for data transformation.
8. Modern Web Applications:
o The MERN stack is well-suited for building single-page applications
(SPAs) and progressive web applications (PWAs), which are in high
demand for their seamless user experiences and offline capabilities.
9. Flexibility and Customization:
o Developers have the flexibility to customize each component according
to their project requirements. The modular nature of the stack allows for
the integration of additional tools and libraries as needed, providing a
tailored development experience.
10. Strong Ecosystem:
o Each component of the MERN stack has a strong ecosystem with
numerous third-party libraries, tools, and middleware available. This
ecosystem support enhances the development process by providing
ready-made solutions for common challenges.
Advantages of MERN Stack
1. Full-Stack Development with JavaScript: One of the most significant
advantages of the MERN stack is that it allows developers to use JavaScript
throughout the entire development process, from front-end to back-end, which
can streamline the development and debugging process.
2. Powerful and Flexible: Each component of the MERN stack is powerful on
its own. MongoDB is highly flexible for storing various types of data.
Express.js simplifies the process of building robust APIs. React enables the
creation of dynamic and responsive user interfaces, and Node.js handles
server-side operations efficiently.
© Edunet Foundation. All rights reserved. | 25
3. Open Source and Community Support: All components of the MERN stack
are open source and have large communities, which means abundant
resources, tutorials, and third-party tools are available to assist in
development.
4. Scalability: Applications built using the MERN stack can be easily scaled
horizontally. MongoDB is designed to handle large volumes of data and can
scale out by sharding. Node.js can handle numerous simultaneous
connections with high throughput, making it ideal for scalable network
applications.
5. Performance: Node.js is known for its non-blocking, event-driven
architecture, which can handle many connections simultaneously, leading to
efficient and fast performance.
6. Rich Ecosystem: The npm registry provides access to a large number of
libraries and tools, which can enhance development efficiency and add
functionalities without having to build them from scratch.
Disadvantages of MERN Stack
1. Learning Curve: While JavaScript is a single language used throughout,
mastering each component of the MERN stack (especially React) can be
challenging for beginners.
2. Performance Bottlenecks: MongoDB, while flexible, may not be as
performant for complex queries compared to traditional SQL databases. This
could lead to performance bottlenecks in applications that require heavy data
manipulation.
3. SEO Challenges: React applications can be challenging to optimize for
search engines out of the box. Server-side rendering or using frameworks
like Next.js can help, but this adds complexity to the project.
4. Data Migration: Migrating data from MongoDB to other databases or vice
versa can be complicated, especially when dealing with large datasets.
5. Tooling and Boilerplate: Setting up a MERN stack project requires
configuring multiple tools and creating boilerplate code, which can be time-
consuming.
6. Complex State Management: Managing state in React can become complex,
especially in larger applications. Libraries like Redux can help, but they also
add to the learning curve and complexity.
1.3 Static application
1.3.1 Overview
Introduction to Static Applications: A static application consists of web pages with
fixed content that doesn't change in response to user actions. These applications are
straightforward and quick to load because they don't require server-side processing.
Static applications are ideal for websites where the content remains consistent over
time, such as personal blogs, portfolios, and informational websites.
© Edunet Foundation. All rights reserved. | 26
Technologies Used to Develop Static Applications:
1. HTML (HyperText Markup Language):
o HTML is the foundational language for creating web pages. It uses tags
to structure content, such as headings, paragraphs, images, and links.
HTML elements form the building blocks of all websites.
2. CSS (Cascading Style Sheets):
o CSS is used to control the presentation and layout of web pages. It allows
developers to apply styles, such as colors, fonts, spacing, and positioning, to
HTML elements. CSS helps in creating visually appealing and responsive
designs.
3. JavaScript (JS):
JavaScript is a programming language that adds interactivity and dynamic behavior
to web pages. It can manipulate HTML and CSS, handle events, and perform actions
such as form validation, creatingimage sliders, and displaying alerts.
These technologies work together to create static applications, with HTML providing
the structure, CSS defining the style, and JavaScript adding interactivity.
1.3.2 Tools and Editors
Visual Studio Code (VS Code) is a free, open-source code editor developed by
Microsoft. It's designed for a wide range of programming tasks and supports numerous
languages and frameworks. VS Code is highly extensible and customizable, making
it a popular choice among developers.
Features of VS Code:
Intelligent Code Completion:
VS Code offers IntelliSense, which provides smart completions based on variable
types, function definitions, and imported modules.
Debugging:
Integrated debugging support allows developers to debug code right within the editor.
It supports breakpoints, call stacks, and an interactive console.
Version Control:
Built-in Git support enables seamless version control, allowing developers to manage
repositories, stage changes, commit, and push updates directly from the editor.
Extensions and Customization:
The rich extension marketplace allows users to install various plugins and themes to
enhance functionality. Users can customize their development environment to suit
their preferences.
© Edunet Foundation. All rights reserved. | 27
Integrated Terminal:
VS Code includes an integrated terminal, enabling developers to run command-line
tasks without leaving the editor.
Code Navigation:
Features like Go to Definition, Find All References, and Symbol Search help
developers navigate large codebases efficiently.
Multiple Language Support:
Out-of-the-box support for languages like JavaScript, Python, Java, C++, and many
more. Extensions can add support for additional languages.
Live Share:
Live Share allows real-time collaboration between developers, enabling pair
programming and code reviews from different locations.
Advantages of VS Code:
1. Lightweight and Fast:
o VS Code is known for its performance. It is lightweight yet powerful, making it
suitable for both small scripts and large projects.
2. Cross-Platform:
o It runs on Windows, macOS, and Linux, providing a consistent development
environment across different operating systems.
3. Highly Customizable:
o Users can tweak the editor's settings, keybindings, and themes. The vast library
of extensions further extends its capabilities.
4. Strong Community and Ecosystem:
o An active community contributes to a rich ecosystem of extensions, tutorials,
and support, making it easy for developers to find resources and get help.
5. Frequent Updates:
o Microsoft regularly updates VS Code, adding new features, improving
performance, and fixing bugs.
Disadvantages of VS Code:
1. Learning Curve:
o While user-friendly, beginners might find the extensive customization options
and numerous features overwhelming initially.
2. Resource Usage:
o Although lightweight compared to full-fledged IDEs, VS Code can consume significant
memory and CPU resources, especially with multiple extensions installed.
3. Dependency on Extensions:
o Heavy reliance on extensions for language-specific features might lead to
inconsistencies or issues when the extensions are not well-maintained.
4. Limited Integrated Tools:
© Edunet Foundation. All rights reserved. | 28
o Unlike some integrated development environments (IDEs), VS Code may lack built-
in tools for certain languages or frameworks, requiring additional setup and
extensions.
1.3.3 Environment setup
Quick Preview to Install Visual Studio Code on Windows:
o Download the VS Code file from the Official Website.
o Execute the download file.
o Accept the Terms & Conditions.
o Click on the Install button.
o Wait for the installation to complete.
o Click on the Launch button to start it.
Steps to Install Visual Studio Code on Windows
Step 1: Visit the Official Website of the Visual Studio Code using any web
browser like Google Chrome, Microsoft Edge, etc.
Figure 13. Download Visual Studio Code
Images Source: https://code.visualstudio.com/download
Step 2: Press the “Download for Windows” button on the website to start the download of the Visual
Studio Code Application.
Step 3: When the download finishes, then the Visual Studio Code Icon appears in the
downloads folder.
© Edunet Foundation. All rights reserved. | 29
Figure 14- VSCODE User Setup
Step 4: Click on the Installer icon to start the installation process of the Visual Studio
Code.
Step 5: After the Installer opens, it will ask you to accept the terms and conditions of the
Visual Studio Code. Click on I accept the agreement and then click the Next button.
Figure 15-Setup License Agreement
Step 6: Choose the location data for running the Visual Studio Code. It will then ask you
to browse the location. Then click on the Next button.
© Edunet Foundation. All rights reserved. | 30
Figure 16. Select Additional Task
Step 7: Then it will ask to begin the installation setup. Click on the Install button.
Figure 17. Ready to install
© Edunet Foundation. All rights reserved. | 31
Step 8: After clicking on Install, it will take about 1 minute to install the Visual Studio
Code on your device.
Figure 18. Installing
Step 9: After the Installation setup for Visual Studio Code is finished, it will show a
window like this below. Tick the “Launch Visual Studio Code” checkbox and then
click Next.
Figure 19. Launch Visual Studio Code
Step 10: After the previous step, the Visual Studio Code window opens successfully.
Now you can create a new file in the Visual Studio Code window and choose a language
of yours to begin your programming journey!
© Edunet Foundation. All rights reserved. | 32
Figure 20. Get started- welcome page
So this is how we successfully installed Visual Studio Code on our Windows system.
1.4 HTML REFRESHER
1.4.1 Getting Started with HTML
HTML stands for Hyper Text Markup Language, is the standard markup language
used to create web pages. Along with CSS, and JavaScript, HTML is a cornerstone
technology used to create web pages, as well as to create user interfaces for mobile
and web applications.
HTML stands for Hyper Text Markup Language
HTML elements are the building blocks of HTML pages
HTML describes the structure of Web pages using HyperText markup language
HTML elements are represented by tags
When you test your page on browsers. Browsers do not display the HTML
tags but use them to render the content of the page.
HTML page extension always will be .html (example.html)
© Edunet Foundation. All rights reserved. | 33
Features of HTML:
It is easy to learn and easy to use.
It is platform-independent.
Images, video, and audio can be added to a web page.
Hypertext can be added to the text.
It is a markup language.
Advantages:
HTML is used to build a website.
It is supported by all browsers.
It can be integrated with other languages like CSS, JavaScript, etc.
Disadvantages:
HTML can create only static webpages so for dynamic web pages other
languages have to be used.
A large amount of code has to be written to create a simple web page.
The security feature is not good.
Creating HTML Document:
Creating an HTML document is easy. To begin coding HTML you need only two things:
a simple text editor and a web browser. Notepad is the most basic of simple- text
editors and you will probably code a fair amount of HTML with it.
Open Notepad or another text editor.
At the top of the page type <html>.
On the next line, indent spaces and now add the opening header tag: <head>.
On the next line, indent ten spaces and type <title> </title>.
Go to the next line, indent five spaces from the margin, and insert the closing
header tag: </head>.
Five spaces in from the margin on the next line, type <body>.
Now drop down another line and type the closing tag right below its mate:
</body>.
Finally, go to the next line and type </html>.
In the File menu, choose Save As.
In the Save as Type option box, choose All Files.
Name the file template.html.
Click Save.
© Edunet Foundation. All rights reserved. | 34
Figure 21. HTML Page structure
Image Source: https://qatechhub.com/html-page-structure-nesting/
<DOCTYPE! html>: This tag is used to tell the HTML version. This currently tells that
the version is HTML 5.
<html>: This is called the HTML root element and is used to wrap all the code.
<head>: Head tag contains metadata, title, page CSS etc. All the HTML elements that
can be used inside the <head> element are: <style> ,<title> ,<base> ,<noscript>
,<script> ,<meta> ,<title> ,etc.
<body>: The body tag is used to enclose all the data that a web page has from texts
to links. All of the content that you see rendered in the browser is contained within this
element.
Code:
Index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page Title</title>
</head>
<body>
<body>
<h1>This is a heading</h1>
<p>This is a paragraph.</p>
<p>This is another paragraph.</p>
© Edunet Foundation. All rights reserved. | 35
</body>
</html>
Output:
1.4.2 HTML Formatting Tags
HTML also defines special elements for defining text with a special meaning. The
formatting tags are divided into two categories: physical tags, used for text styling
(visual appearance of the text), and logical or semantic tags used to add semantic
value to the parts of the text (for example, let the search engines know whatkeywords
should be web page ranked for).
HTML uses elements like <b> and <i> for formatting output, like bold or italic text.
Formatting elements were designed to display special types of text:
<b> - Bold text
<strong> - Important text
<i> - Italic text
<em> - Emphasized text
<mark> - Marked text
<small> - Small text
<del> - Deleted text
<ins> - Inserted text
<sub> - Subscript text
<sup> - Superscript text
<b> and <strong> Tags
The <b> tag is a physical tag that stands for bold text, whereas the <strong> tag
being a logical tag is used to emphasize the importance of the text.
<b>This text is bold</b>
<strong>This text is strong</strong>
© Edunet Foundation. All rights reserved. | 36
<i> and <em> Tags
The <i> and <em> tags define italic text. The <i> tag is only responsible for visual
appearance of the enclosed text, without any extra importance. The <em> tagdefines
emphasized text, with added semantic importance.
<i>This text is italic</i>
<em>This text is emphasized</em>
<pre> Tag
The <pre> tag is used to define preformatted text. The browsers render the enclosed
text with white spaces and line breaks.
<pre>Spaces
and line breaks within this element
are shown as typed.
</pre>
<mark> Tag
The <mark> tag is used to present a part of text in one document as marked or
highlighted for reference purposes.
<small> Tag
The <small> tag decreases the text font size by one size smaller than a document's
base font size (from medium to small, or from x-large to large).
The tag usually contains items of secondary importance such as copyright notices,
side comments, or legal notices.
<p>The interest rate is only 10%*</p>
<small>* per day</small>
<big> Tag
The <big> tag defines bigger text.
<p><big>Bigger text</big></p>
<del> and <s> Tags
The <del> tag specifies a part of the text that was deleted from the document. Browsers
display this text as a strikethrough.
<p> She likes <del>violets</del> snowdrops․</p>
<p><s>I am studying in high school.</s></p>
The <s> tag defines text that is no longer correct, or relevant.
The content of both tags is displayed as strikethrough. However, despite the visual
similarity, these tags cannot replace each other.
© Edunet Foundation. All rights reserved. | 37
<ins> and <u> Tags
The <ins> tag defines the text that has been inserted (added) to the document. The
content of the tag is displayed as underlined.
<p>She likes <del>violets</del> <ins>snowdrops</ins>․ </p>
The <u> tag specifies text that is stylistically different from normal text, i.e. words or
fragments of text that need to be presented differently. This could be misspelled words
or proper nouns in Chinese.
<p>Here we used <u>the <u> tag</u>.</p>
<sub> and <sup> Tag
The <sub> defines subscript texts. Subscript text is under the baseline of other
symbols of the line and has a smaller font. The <sup> tag defines superscript, which
is set slightly above the normal line of type and is relatively smaller than the rest of the
text. The baseline passes through the upper or lower edge of the symbols.
<p>The formula of water is H<sub>2</sub>O, and the formula of alcohol is
C<sub>2</sub>H<sub>5</sub>ОН </p>
<p>E = mc<sup>2</sup>, where E — kinetic energy, m — mass, c — the speed of light.
</p>
<dfn> Tag
The <dfn> tag is used to define the term, that is mentioned for the first time. Thecontent
of the tag is displayed in italic.
<p><dfn>HTML</dfn> (HyperText Markup Language ) — The standardized markup
language for documents on the World Wide Web. Most web pages contain a description
of the markup in the language HTML</p>
<p>, <br> and <hr> Tags
The <p> tag defines the paragraph. Browsers automatically add 1em margin before
and after each paragraph.
<p>The first paragraph</p>
The <br> tag inserts a single line break. Unlike the <p> tag an empty indent is
not added before the line.
<h1>How to use the <br> tag</h1>
<p> We can insert the <br /> tag inside the paragraph, <br /> to transfer
a part of the text to another line if necessary.</p>
In HTML5 the <hr> tag defines a thematic change between paragraph-level elements
in an HTML page. In previous versions of HTML, it was used to draw a horizontal line
on the page visually separating the content. In HTML5 the elementhas semantic
meaning.
© Edunet Foundation. All rights reserved. | 38
<h1>Football</h1>
<p>Team sports involve, to varying degrees, kicking a ball with a foot to score a
goal.</p>
<hr>
<h1>Basketball</h1>
<p>A game played between two teams of five players in which goals are scored by
throwing a ball through a netted hoop fixed at each end of the court.</p>
Note: Some formatting tags like <b>, <u>, <small>, <big>, <i>, <mark>, <ins>,
<del>, etc are not used as the same properties are added as a CSS property in
CSS3 andHTML5. Initially, in HTML4 we were utilizing these tags but after adding the
same properties in CSS, avoid using these tags while designing web pages.
1.4.3 HTML Block Component
HTML Blocks are grouping items of HTML elements. Each HTML element has its
own display based on its type. However, HTML blocks also have display but can group
the other HTML elements also as block.
By default, all block-level elements are starts in a new line. The elements added after
block-level elements will start from a new line. Block-level elements can contain other
block-line elements as nested block-line elements. Block-level elements can stretch to
the browser’s full width
Below are the some of block-level elements:
<address> - Specifies the contact information for a page or document
<form> - A Facility to submit the input data by user
<blockquote> - used to define a quote section
<p> - Paragraph
<pre> - Preformatted text in HTML document
<h1> to <h6> - Used to define HTML headings
<dd> - Used to specify the term/description/name in a description list
<div> - used to create block-level elements
<table> - represents a table in an HTML document
<ol> - Ordered list in html documents
<ul> - Unordered list in HTML document
<nav> - Specifies the navigation area
Block elements can be divided into two types.
Inline Elements
Group Elements
© Edunet Foundation. All rights reserved. | 39
Inline elements
The inline elements do not start at the newline. The inline elements always start in the
middle of the line and are part of another element. The below list is the inline elements.
<b> - used to display the text as bold
<i> - Alternate Voice or different quality of text
<u> - Unarticulated text/underlined text in HTML document
<p> - Paragraph
<address> - Specifies the contact information for a page or document
<form> - A Facility to submit the input data by user
<li> - used to represent a list item in HTML document
<ins> - Editorial Insertion
<del> - Used for editorial deletion
<code> - Used to define the computer code
Group elements
The Group elements always start with new line. The Group elements are used to group
other elements. <div> and <span> are the majorly used Group elements.
<div>: <div> is mostly used to create block-level elements. In other words, <div> tag
is used to define a section in HTML documents. Except <div>, all others have their
own display. The tag can be coded like <div></div> with its contents/other HTML
tags inserted between the opening and closing tags. <div> also acts as a block-level
element that is used as a container for other HTML elements. The <div> element has
no additional attributes by default. style and class are commonly provided with DIV
elements. When <div> element is used together with CSS, the style blocks can be
used together. All browsers always place a line break before and after the <div> tag
by default.
Syntax -
<div> .... </div>
<span>: Generic container for text or group inline-elements HTML. The <span> tag
used to specify the generic container for inline elements and content. There no visual
change that can be done by <span> tag. It doesn’t represent anything other than its
children. The tag can be specified like <span class=""></span> with the content
between the opening and closing tags.
Syntax -
<span>.. text here.. </span>
1.4.4 List
HTML List Tags are used to specify information in the form of a list. HTML Lists are
very useful to group related information together. Often List items look well- structured
© Edunet Foundation. All rights reserved. | 40
and they are easy to read for users. A list can contain one or more list elements.
HTML List Types
List Type Description Tags used
Unordered
used to group a set of items without any order. <ul>,<li>
List
Ordered List used to group a set of items, in a specific order. <ol>,<li>
Definition used to display some definition term (dt) &
<dl>,<dt>,<dd>
List definition’s description (dd)
Unordered List:
Unordered lists are used to list a set of items when they have no special order or
sequence. It is also called a bulleted list. An unordered list is created using HTML <ul>
tag. Each item in the list starts with the <li> tag.
Example Code:
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
Output:
HTML List Types
List Style
Description Example & Syntax
Type
disc Starts a list using discs type bullets (default) <ul type="disc">
circle Starts a list using circle-type bullets <ul type="circle">
square Starts a list using square-type bullets <ul type="square">
none Starts a list without bullets <ul type="none">
Ordered List:
Ordered list is used to list related items in a numbered or other specific order. This is
useful when you want to show counts of items in some way. The ordered list is created
using HTML <ol> tag. Each item in the list is with the <li> tag.
Example Code:
<ol>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ol>
© Edunet Foundation. All rights reserved. | 41
Output:
HTML Ordered List Style Type Attribute
Example and
List Style Type Description
Syntax
Numbers Starts a list using numbers (default) <ol type="1">
Uppercase letters Starts a list using uppercase letters <ol type="A">
Lowercase letters Starts a list using lowercase letters <ol type="a">
Uppercase roman Starts a list using uppercase roman
<ol type="I">
numbers numbers
Lowercase roman Starts a list using lowercase roman
<ol type="i">
numbers numbers
Definition List or Description List:
The definition list is different from the other two types of lists. No bullet or number is
provided for the list of items. In this list type, the list element has two parts.
(1) A definition term and (2) The definition description
The definition list is surrounded within <DL> ……. </DL> tags. Definition
term is presented in between <DT> ….. </DT> tag and
Definition description should be surrounded within <DD> ................. </DD> tag.
Example Code:
<dl>
<dt>Coffee</dt>
<dd>- black hot drink</dd>
<dt>Milk</dt>
<dd>- white cold drink</dd>
</dl>
Output:
© Edunet Foundation. All rights reserved. | 42
1.4.5 Table
You can create tables for your website using the <table> tag in conjunction with the
<tr>, <td> and <th> tags. The HTML tables allow displaying the data (e.g. image, text,
link) in columns and rows of cells. Table rows may be grouped into head, foot, and
body sections (via the <thead>, <tfoot>, and <tbody> elements, respectively).
The <caption> tag defines a table caption. A <caption> tag must be inserted
immediately after the <table> tag.
Note: You can specify only one caption per table.
cellpadding - The cell padding attribute places spacing around data within each cell.
cellspacing - The cell spacing attribute places space around each cell in the table.
th- Table Head
tr- Table Row
td- Table Data
Example Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page Title</title>
</head>
<body>
<body>
<table border=2>
<tr>
<th>Company</th>
<th>Contact</th>
<th>Country</th>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
<tr>
<td>Centro comercial Moctezuma</td>
<td>Francisco Chang</td>
<td>Mexico</td>
</tr>
</table>
</body></html>
© Edunet Foundation. All rights reserved. | 43
Output:
1.4.6 Link
HTML links are hyperlinks. You can click on a link and jump to another document. The
HTML <a> tag defines a hyperlink. The most important attribute of the <a> element is
the href attribute, which indicates the link's destination. The link text is the part that will
be visible to the reader. Clicking on the link text will send the reader to the specified
URL address.
Example Code:
<a href="https://www.edunetfoundation.org/">Visit Edunet Foundation!</a>
Output:
When you click on the link it will showcase the below output on the browser screen
1.4.7 Form
HTML Forms are required to collect different kinds of user inputs, such as contact
details like name, email address, phone numbers, or details like credit card
information, etc.
© Edunet Foundation. All rights reserved. | 44
Forms contain special elements called controls like input box, checkboxes, radio
buttons, submit buttons, etc. Users generally complete a form by modifying itscontrols
e.g., entering text, selecting items, etc., and submitting this form to a web server for
further processing.
Action Attribute: The action attribute defines the action to be performed when the
form is submitted. Usually, the form data is sent to a page on the server when the user
clicks on the submit button.
Example : <form action="/action_page.php">
In the example above, the form data is sent to a page on the server called
"/action_page.php". This page contains a server-side script that handles the form data:
If the action attribute is omitted, the action is set to the current page.
Target Attribute: The target attribute specifies if the submitted result will open in a
new browser tab, a frame, or in the current window. The default value is "_self"
which means the form will be submitted in the current window. To make the form result
open in a new browser tab, use the value "_blank".
Here, the submitted result will open in a new browser tab:
<form action="/action_page.php" target="_blank">
Method Attribute: The method attribute specifies the HTTP method (GET or POST)to
be used when submitting the form data.
<form action="/action_page.php" method="get">
<form action="/action_page.php" method="post">
Label Element: The <label> tag defines a label for many form elements.
The <label> element is useful for screen-reader users because the screen-reader
will read out and load the label when the user is focused on the input element.
Input Element: This is the most commonly used element within HTML forms. It allows
you to specify various types of user input fields, depending on the type attribute. An
input element can be of type text field, password field, checkbox, radio button, submit
button, reset button, file select box, as well as several new input typesintroduced in
HTML5.
<input> element can be displayed in several ways, depending on the type attribute. If
the type attribute is omitted, the input field gets the default type: "text".
Text Fields: Text fields are one line areas that allow the user to input text.
© Edunet Foundation. All rights reserved. | 45
Example Code:
<form> <label>User Name:</label>
<input type="text" name="username" id="username"> </form>
Output:
Password Field: Password fields are similar to text fields. The only difference is;
characters in a password field are masked, i.e. they are shown as asterisks or dots.
This is to prevent someone else from reading the password on the screen.
Example Code:
<form> <label>Password:</label>
<input type="password" name="user-password" id="user-pwd"> </form>
Output:
Radio Button Field: Radio buttons let a user select ONLY ONE of a limited number of
choices.
Example Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page Title</title>
</head>
<body>
<body>
<form>
<input type="radio" id="html" name="fav_language" value="HTML">
<label>HTML</label><br>
<input type="radio" id="css" name="fav_language" value="CSS">
<label>CSS</label><br>
<input type="radio" id="javascript" name="fav_language" value="JavaScript">
<label>JavaScript</label><br><br>
</form>
</body></html>
© Edunet Foundation. All rights reserved. | 46
Output:
Check box Field: Checkboxes let a user select ZERO or MORE options of a limitednumber
of choices
Example Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page Title</title>
</head>
<body>
<body>
<form>
<input type="checkbox" id="vehicle1" name="vehicle1" value="Bike">
<label> I have a bike</label><br>
<input type="checkbox" id="vehicle2" name="vehicle2" value="Car">
<label> I have a car</label><br>
<input type="checkbox" id="vehicle3" name="vehicle3" value="Boat">
<label> I have a boat</label><br><br>
</form>
</body>
</html>
Output:
Other input types:
Button – to create button
Color - a color picker can show up
Date - a date picker can show up
Email - the e-mail address can be automatically validated when submitted
© Edunet Foundation. All rights reserved. | 47
Image - defines an image as a submit button
File - defines a file-select field and a "Browse" button for file uploads
Hidden - defines a hidden input field (not visible to a user)
Month - allows the user to select a month and year
Number - defines a numeric input field
Range - defines a control for entering a number whose exact value is not important
Submit – used to create submit button
Reset – used to create reset button
Attribute Description
Specifies that an input field should be pre-selected when
checked
the page loads (for type="checkbox" or type="radio")
disabled Specifies that an input field should be disabled
max Specifies the maximum value for an input field
Specifies the maximum number of characters for an
maxlength
input field
min Specifies the minimum value for an input field
Specifies a regular expression to check the input value
pattern
against
Specifies that an input field is read-only (cannot be
readonly
changed)
Specifies that an input field is required (must be filled
required
out)
size Specifies the width (in characters) of an input field
step Specifies the legal number intervals for an input field
value Specifies the default value for an input field
Drop down Field: <select> and <option> tags are used to create a drop down list in
html form.
The <select> element defines a drop-down list
The <option> elements define an option that can be selected.
By default, the first item in the drop-down list is selected.
To define a pre-selected option, add the selected attribute to the optionExample
Example Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page Title</title>
</head>
<body>
<body>
<form>
© Edunet Foundation. All rights reserved. | 48
<label for="cars">Choose a car:</label>
<select id="cars" name="cars">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="fiat">Fiat</option>
<option value="audi">Audi</option>
</select>
</form>
</body>
</html>
Output:
1.4.8 Multi-Media
What is Multimedia?
Multimedia comes in many different formats. It can be almost anything you can hear
or see, like images, music, sound, videos, records, films, animations, and more.Web
pages often contain multimedia elements of different types and formats.
Browser Support
The first web browsers had support for text only, limited to a single font in a single
color. Later came browsers with support for colors, fonts, images, and multimedia!
Multimedia Formats
Multimedia elements (like audio or video) are stored in media files.The most common
way to discover the type of a file, is to look at the file extension.Multimedia files have
formats and different extensions like: .wav, .mp3, .mp4, .mpg, .wmv, and
.a
Figure 22. HTML video Format Reference
Figure 23. HTML Audio Format Reference
ImageSource: https://www.sitesbay.com/html5/index
© Edunet Foundation. All rights reserved. | 49
The HTML5 <audio> element has specified a standard method to embed audio in a
web page.
Example Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page Title</title>
</head>
<body>
<body>
<audio controls>
<source src="horse.ogg" type="audio/ogg">
<source src="horse.mp3" type="audio/mpeg"> Your browser does not support the
audio element.
</audio>
</body>
</html>
Output:
The controls attribute is used to add audio controls, like play, pause, and volume. Text
between the <audio> and </audio> tags will be displayed in browsers which does not
support the <audio> element.
Multiple <source> elements can be linked to different audio files. The browser will be
using the first recognized format.
The HTML5 <video> element is used to specify a standard way of embedding a video
in a web page.
© Edunet Foundation. All rights reserved. | 50
Example Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page Title</title>
</head>
<body>
<body>
<video width="320" height="240" controls>
<source src="movie.mp4" type="video/mp4">
<source src="movie.ogg" type="video/ogg"> Your browser does not support the
video tag.
</video>
</body>
</html>
Output:
The controls attribute is used to add video controls, like play, pause, and volume. It
is a good method to always use width and height attributes. If height and width are not
mentioned, the browser will not know the size of the video. The effect of this is that
page will be changing (or flicking) while the video gets loaded. Text between the
<video> and </video> tags will only get displayed in browsers that do not support the
<video> element. Multiple <source> elements can be used to link different video files.
The browser will be using the first recognized format.
1.4.9 Iframe
An HTML iframe is used to display a web page within a web page. The HTML
<iframe> tag specifies an inline frame. An inline frame is used to embed another
document within the current HTML document.
© Edunet Foundation. All rights reserved. | 51
Example Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page Title</title>
</head>
<body>
<body>
<iframe src="demo_iframe.html" height="200" width="300" title="Iframe
Example"></iframe>
</body>
</html>
Output:
1.4.10 Layout Elements
HTML has several semantic elements that define the different parts of a web page:
<header> - Defines a header for a document or a section
<nav> - Defines a set of navigation links
<section> - Defines a section in a document
<article> - Defines an independent, self-contained content
<aside> - Defines content aside from the content (like a sidebar)
<footer> - Defines a footer for a document or a section
<details> - Defines additional details that the user can open and close on demand
<summary> - Defines a heading for the <details> element
© Edunet Foundation. All rights reserved. | 52
Figure 24. semantic elements
Image Source: https://www.w3schools.com/html/html_layout.asp
1.5 Styling with CSS
1.5.1 What is CSS?
CSS (Cascading Style Sheets) is used to styles web pages. Cascading Style Sheets
are fondly referred to as CSS. The reason for using this is to simplify the process of
making web pages presentable. It allows you to apply styles on web pages. More
importantly, it enables you to do this independently of the HTML that makes up each
web page.
1.5.2 Why we learn CSS?
Styling is an essential property for any website. It increases the standards and overall
look of the website that makes it easier for the user to interact with it. A website can
be made without CSS, as styling is MUST since no user would want to interact with a
dull and shabby website. So, for knowing Web Development, learning CSS is
mandatory.
<!DOCTYPE html>
<html>
<head>
<title>My First CSS Example</title>
<style> body {
background-color: lightblue;
}
h1 {
color: white;
text-align: center;
}
p {
© Edunet Foundation. All rights reserved. | 53
font-family: verdana; font-size: 20px;
}
</style>
</head>
<body>
<h1>My First CSS Example</h1>
<p>This is a paragraph with some text.</p>
</body>
</html>
Output:
Types of CSS: There are three types of CSS which are given below.
Inline: Inline CSS contains the CSS property in the body section attached with
the element known as inline CSS.
Internal or Embedded: The CSS ruleset should be within the HTML file in
thehead section i.e the CSS is embedded within the HTML file.
External: External CSS contains a separate CSS file that contains only style
properties with the help of tag attributes.
External CSS: External CSS contains a separate CSS file with a .css extension
which contains only style property with the help of tag attributes.
selector{
property1: value1;
property2: value2;
}
Include external CSS file: The external CSS file is linked to the HTML document
using a link tag.
<link rel="stylesheet" type="text/css" href="/style.css" />
Internal CSS or Embedded: CSS is embedded within the HTML file using a style
HTML tag.
<style type="text/css">
div { color: #444;}
</style>
Inline CSS: It contains CSS properties in the body section specified within HTML
tags.
<tag style="property: value"> </tag>
CSS Key Features:
CSS specifies how HTML elements should be displayed on screens.
© Edunet Foundation. All rights reserved. | 54
The Major key feature of CSS includes styling rules which are interpreted by
the client browser and applied to various elements.
Using CSS, you can control the color text, the style of fonts, spacing between
elements, how columns are sized, variation in display for different devices and
screen size as well as a variety of other effects.
1.5.3 Selectors
To apply CSS to an element you need to select it. CSS provides you with a number
of different ways to do this
If you've got some text that you only want to be larger and red if it's the first
paragraph of an article, how do you do that?
<article>
<p>I want to be red and larger than the other text.</p>
<p>I want to be normal sized and the default color.</p>
</article>
You use a CSS selector to find that specific element and apply a CSS rule, like this.
article p:first-of-type {
color: red;
font-size: 1.5em;
}
CSS provides you with a lot of options to select elements and apply rules to them,ranging
from very simple to very complex, to help solve situations like this.
Code:
<!DOCTYPE html>
<html>
<head>
<style>
article p:first-of-type { color: red;
font-size: 1.5em;
}
</style>
</head>
<body>
<article>
<p>I want to be red and larger than the other text.</p>
<p>I want to be normal sized and the default colour.</p>
</article>
</body>
</html>
© Edunet Foundation. All rights reserved. | 55
Output:
The parts of a CSS rule
To understand how selectors work and their role in CSS, it's important to know the
parts of a CSS rule. A CSS rule is a block of code, containing one or more selectors
and one or more declarations.
Figure 25. Part of CSS Rule-selectors
Image Source: https://web.dev/learn/css/selectors
In this CSS rule, the selector is .my-css-rule which finds all elements with a class
of my-css-rule on the page. There are three declarations within the curly brackets. A
declaration is a property and value pair which applies styles to the elements matched
by the selectors.
Used to find or select the HTML elements you want to style. These are categorized as
follows:
A universal selector—also known as a wildcard—matches any element.
*{
color: hotpink;
}
This rule causes every HTML element on the page to have hotpink text.
© Edunet Foundation. All rights reserved. | 56
Type selector
A type selector matches a HTML element directly.
section {
padding: 2em;
}
This rule causes every <section> element to have 2em of padding on all sides.
Class selector
A HTML element can have one or more items defined in their class attribute.The
class selector matches any element that has that class applied to it.
<div class="my-class"></div>
<button class="my-class"></button>
<p class="my-class"></p>
Any element that has the class applied to it will get coloured red:
.my-class {
color: red;
}
A HTML element that has a class of .my-class will still be matched to the above CSS
rule, even if they have several other classes, like this:
<div class="my-class another-class some-other-class"></div>
This is because CSS looks for a class attribute that contains the defined class, rather
than matching that class exactly.
ID selector
An HTML element with an id attribute should be the only element on a page with thatID
value. You select elements with an ID selector like this:
#rad {
border: 1px solid blue;
}
This CSS would apply a blue border to the HTML element that has an id of rad, like
this:
<div id="rad"></div>
Attribute selector
© Edunet Foundation. All rights reserved. | 57
You can look for elements that have a certain HTML attribute, or have a certain value
for an HTML attribute, using the attribute selector. Instruct CSS to look for attributes
by wrapping the selector with square brackets ([ ]).
[data-type='primary'] {
color: red;
}
This CSS looks for all elements that have an attribute of data-type with a valueof
primary, like this:
<div data-type="primary"></div>
Instead of looking for a specific value of data-type, you can also look for elements
with the attribute present, regardless of its value.
[data-type] {
color: red;
}
<div data-type="primary"></div>
<div data-type="secondary"></div>
Both of these <div> elements will have red text.
You can use case-sensitive attribute selectors by adding an s operator to yourattribute
selector.
[data-type='primary' s] {
color: red;
}
This means that if a HTML element had a data-type of Primary, instead of primary, it
would not get red text. You can do the opposite—case insensitivity—by using
an i operator.
Along with case operators, you have access to operators that match portions of
strings
inside attribute values.
Code:
/* A href that contains "example.com" */
[href*='example.com'] {
color: red;
}
/* A href that starts with https */
[href^='https'] {
color: green;
}
/* A href that ends with .com */
[href$='.com'] {
© Edunet Foundation. All rights reserved. | 58
color: blue;
}
Grouping selectors
A selector doesn't have to match only a single element. You can group multiple
selectors by separating them with commas:
strong,
em,
.my-class,
[lang] {
color: red;
}
1.5.4 What Is CSS Box Model?
The CSS Box Model describes all the HTML elements of the webpage as rectangular
boxes. As shown in the graphic below, let it be the logo, contents of the navigation bar
or buttons, everything is a box.
Figure 26. CSS Box Model
© Edunet Foundation. All rights reserved. | 59
Figure 27. Box sizing
The CSS box model comprises the box-sizing, padding and margin properties.
How to Setup the Project
HTML:
Open VS Code or Notepad++ and write this code inside the body tag:
<div class="box-1"> Box-1 </div>
CSS:
Clear the default styles of our browser
*{
margin: 0px;
padding: 0px;
font-family: sans-serif;
}
Now, let's style our box
.box-1 {
width: 300px;
background-color: skyblue;
font-size: 50px;
}
Output:
© Edunet Foundation. All rights reserved. | 60
The Padding Property
The CSS padding properties are used to generate space around an element'scontent,
inside of any defined borders.
With CSS, you have full control over the padding. There are properties for setting the
padding for each side of an element (top, right, bottom, and left).
How to use the padding property in CSS
This is the shorthand of the four padding properties:
padding-top
padding-right
padding-bottom
padding-left
Figure 28. Padding for all the four sides
Let's add some padding to our content.
// Padding added on top, right, left, bottom of .box-1
<!DOCTYPE html>
<html>
<head>
<style>
.box-1 {
margin: 0px;
padding: 0px;
font-family: sans-serif;
width: 300px;
background-color: skyblue;
height: 100px;
font-size: 50px;
}
</style>
</head>
<body>
© Edunet Foundation. All rights reserved. | 61
<div class="box-1">
This is some text in a box
</div>
</body>
</html>
Ouput:
Let's try adding padding to just 1 side of our content (only the right side):
.box-1{
padding: 0 100px 0 0;
}
// Or you can use
.box-1{
padding-right: 100px;
}
© Edunet Foundation. All rights reserved. | 62
The Border Property:
The CSS border properties allow you to specify the style, width, and color of an
element's border.
How to use the border property in CSS
the border is the space added on top of our main content + padding
There are three crucial inputs of the border property:
border size : in px
border style : solid / dotted/ dashed
border color : name of color
Figure 29. Borders for all the four sides
Write this code in your CSS,
.box-1 {
width: 300px;
font-size: 50px;
padding: 50px;
border: 10px dashed black;
}
© Edunet Foundation. All rights reserved. | 63
Output:
The Margin Property
The CSS margin properties are used to create space around elements, outside of
any defined borders.
How to use margin property in CSS
This is the shorthand for the four properties of the margin property:
margin-top
margin-right
margin-bottom
margin-left
Figure 30. Margin for all the four sides
.box-1 {
padding: 50px;
border: 10px dashed black;
margin: 50px;
}
© Edunet Foundation. All rights reserved. | 64
Output:
Let's try adding a margin to just 1 side of our content (only the left side):
Output:
1.5.4 CSS Colors/Backgrounds
Using Color Name
Example Code:
<html>
<head>
<style>
:root {
--main-bg-color: cyan;
--main-text-color: pink;
© Edunet Foundation. All rights reserved. | 65
}
body {
background-color: var(--main-bg-color);
color: var(--main-text-color);
text-align: center;
}
</style>
</head>
<body>
<h1>CSS Color</h1>
</body>
</html>
Output:
Using HEX Format
Hexadecimal can be defined as a six-digit color representation. This notation starts
with the # symbol followed by six characters ranges from 0 to F. In hexadecimal
notation, the first two digits represent the red (RR) color value, the next two digits
represent the green (GG) color value, and the last two digits represent the blue (BB)
color value.
The black color notation in hexadecimal is #000000, and the white color notation in
hexadecimal is #FFFFFF. Some of the codes in hexadecimal notation are #FF0000,
#00FF00, #0000FF, #FFFF00, and many more.
color:#(0-F)(0-F)(0-F)(0-F)(0-F)(0-F);
Example Code:
<html>
<head>
<style>
:root {
--main-bg-color: #aeaeae;
--main-text-color: #000;
}
© Edunet Foundation. All rights reserved. | 66
body {
background-color: var(--main-bg-color);
color: var(--main-text-color);
text-align: center;
}
</style>
</head>
<body>
<h1>CSS Color</h1>
</body>
</html>
Output:
Using RGB Format
RGB format is the short form of 'RED GREEN and BLUE' that is used for defining the
color of an HTML element simply by specifying the values of R, G, B that are in the
range of 0 to 255.
The color values in this format are specified by using the rgb() property. Thisproperty
allows three values that can either be in percentage or integer (range from 0to 255).
This property is not supported in all browsers; that's why it is not recommended to use
it.
Syntax
color: rgb(R, G, B);
© Edunet Foundation. All rights reserved. | 67
Example Code:
<html>
<head>
<style>
:root {
--main-bg-color: rgb(238, 130, 238);
--main-text-color: rgb(255, 255, 255);
}
body {
background-color: var(--main-bg-color);
color: var(--main-text-color);
text-align: center;
}
</style>
</head>
<body>
<h1>CSS Color</h1>
</body>
</html>
Output:
Using HSL Format
It is a short form of Hue, Saturation, and Lightness. Let's understand them individually.
Hue: It can be defined as the degree on the color wheel from 0 to 360. 0 represents
red, 120 represents green, 240 represents blue.
Saturation: It takes value in percentage in which 100% represents fully saturated, i.e.,
no shades of gray, 50% represent 50% gray, but the color is still visible, and 0%
represents fully unsaturated, i.e., completely gray, and the color is invisible.
Lightness: The lightness of the color can be defined as the light that we want to
provide the color in which 0% represents black (there is no light), 50% represents
neither dark nor light, and 100% represents white (full lightness).
© Edunet Foundation. All rights reserved. | 68
Example Code:
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-image: url("wallpaper.jpg");
background-repeat: no-repeat;
background-position: center;
background-size: cover;
}
</style>
</head>
<body>
</body>
</html>
Output:
1.6.5 CSS Text Property
Text-Align
The text-align-last property in CSS is used to set the last line of the paragraph just
before the line break.
Syntax:
text-align-last: auto | start | end | left | right | center | justify | initial | inherit;
Default Value : Its default value is auto.
Example Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Text Alignment Demo</title>
<style>
.container {
© Edunet Foundation. All rights reserved. | 69
border: 1px solid #ddd; padding: 10px;
margin: 10px;
display: inline-block; width: 200px;
}
.text-left {
text-align: left;
}
.text-right {
text-align: right;
}
.text-center {
text-align: center;
}
.text-justify {
text-align: justify;
}
.text-start {
text-align: start;
}
.text-end {
text-align: end;
}
/* Demo for text-align-last property */
.single-line {
font-size: 20px; padding-top: 5px;
}
.last-left {
text-align-last: left;
}
.last-right {
text-align-last: right;
}
.last-center {
text-align-last: center;
}
</style>
</head>
© Edunet Foundation. All rights reserved. | 70
<body>
<h1>Text Alignment Examples</h1>
<div class="container text-left"> This text is left-aligned.
</div>
<div class="container text-right"> This text is right-aligned.
</div>
<div class="container text-center"> This text is centered.
</div>
<div class="container text-justify">
This text is justified (fills the entire width).
</div>
<div class="container text-start">
This text is aligned to the left in LTR languages (like English).
</div>
<div class="container text-end">
This text is aligned to the right in LTR languages (like English).
</div>
<h2>Text-align-last for Single Lines</h2>
<p>This line demonstrates the default behavior (text-align-last: inherit) - all
content is aligned left.</p>
<div class="container single-line last-left">
This is a single line with text-align-last: left;
</div>
<div class="container single-line last-right">
This is a single line with text-align-last: right;
</div>
<div class="container single-line last-center">
This is a single line with text-align-last: center;
</div>
</body>
</html>
© Edunet Foundation. All rights reserved. | 71
Output:
Text-Overflow Property
The text-overflow property specifies how overflowed content that is not displayed
should be signaled to the user. It can be clipped, display an ellipsis (...), or display a
custom string.
Both of the following properties are required for text-overflow:
white-space: nowrap;
overflow: hidden;
Columns Property:
The columns property is a shorthand property for:
column-width
column-count
The column-width part will define the minimum width for each column, while the
column-count part will define the maximum number of columns
Example Code:
<!DOCTYPE html>
<style>
.column-container {
/* Adjust the width as needed */ width: 800px;
display: flex; /* For horizontal layout of columns */
}
.column {
/* Adjust the number of columns and gap between them */ column-count: 3;
column-gap: 20px; padding: 10px;
border: 1px solid #ddd;
}
© Edunet Foundation. All rights reserved. | 72
.column p {
/* Optional styling for content within columns */ margin-bottom: 5px;
}
</style>
</head>
<body>
<div class="column-container">
<div class="column">
<p>This is some content for the first column.</p>
<p>Here's another paragraph for the first column.</p>
</div>
<div class="column">
<p>This content goes in the second column.</p>
<p>Another paragraph for the second column.</p>
</div>
<div class="column">
<p>This is in the third column.</p>
<p>One more paragraph for the third column.</p>
</div>
</div>
</body>
</html>
Output:
Text-indent Property
The text-indent property in CSS is used to define the indentation of the first line in each
block of text. It also takes negative values. It means if the value is negativethen
the first line will be indented to the left.
Syntax:
text-indent: length | initial | inherit;
Property values
length: It is used to set fixed indentation in terms of px, pt, cm, em etc. The
default value of length is 0.
© Edunet Foundation. All rights reserved. | 73
Line height Property
The line-height property in CSS is used to set the amount of space used for lines, such
as in the text. Negative values are not allowed.
Syntax:
line-height: normal | number | length | percentage | initial | inherit;
Property values:
normal: This mode represents the normal line height. This is the default value.
initial: This mode is used to set this property to its default value.
number: This value is a unitless number multiplied by the current font-size to
set the line height. In most cases, this is the preferred way to set line height and
avoid unexpected results due to inheritance.
length: In this mode a fixed line height is specified.
percentage: This mode is used to set line height in percent of the current font
size.
Example Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Line Height Demo</title>
<style> body {
font-family: Arial, sans-serif;
}
.container {
border: 1px solid #ddd; padding: 10px;
margin: 10px;
}
.normal-line-height {
line-height: normal; /* Default line height */
}
.large-line-height {
line-height: 2em; /* Line height set to 2 times the font size */
}
.small-line-height {
line-height: 1.2em; /* Line height set to 1.2 times the font size */
}
© Edunet Foundation. All rights reserved. | 74
.number-line-height {
line-height: 50px; /* Line height set to a fixed pixel value */
}
</style>
</head>
<body>
<h1>Line Height Examples</h1>
<div class="container normal-line-height"> This paragraph has the default line
height.
</div>
<div class="container large-line-height">
This paragraph has a larger line height (2 times the font size).
</div>
<div class="container small-line-height">
This paragraph has a smaller line height (1.2 times the font size).
</div>
<div class="container number-line-height">
This paragraph has a fixed line height of 50 pixels.
</div>
</body>
</html>
Output:
1.5.6 CSS FONTS
Font Family
Using a font that is easy to read is important. The font adds value to your text. It is
also important to choose the correct color and text size for the font.
Generic Font Families
In CSS there are five generic font families:
© Edunet Foundation. All rights reserved. | 75
1. Serif fonts have a small stroke at the edges of each letter. They create a
sense of formality and elegance.
2. Sans-serif fonts have clean lines (no small strokes attached). They create a
modern and minimalistic look.
3. Monospace fonts - here all the letters have the same fixed width. They create
a mechanical look.
4. Cursive fonts imitate human handwriting.
5. Fantasy fonts are decorative/playful fonts.
we use the font-family property to specify the font of a text.
Example Code
<!DOCTYPE html>
<html>
<head>
<style>
.p1 {
font-family: "Times New Roman", Times, serif;
}
.p2 {
font-family: Arial, Helvetica, sans-serif;
}
.p3 {
font-family: "Lucida Console", "Courier New", monospace;
}
</style>
</head>
<body>
<h1>CSS font-family</h1>
<p class="p1">This is a paragraph, shown in Times New Roman font.</p>
<p class="p2">This is a paragraph, shown in Arial font.</p>
<p class="p3">This is a paragraph, shown in Lucida Console font.</p>
</body>
</html>
Output:
© Edunet Foundation. All rights reserved. | 76
Font Style
The font-style property is mostly used to specify italic text. The font-weight property
specifies the weight of a font. The font-variant property specifies whether or not a text
should be displayed in a small-caps font.
Font Size
The font-size property sets the size of the text. Setting the text size with pixels, em,
vw, and percentage gives you full control over the text size.
CSS Google Fonts
If you do not want to use any of the standard fonts in HTML, you can use Google
Fonts. Google Fonts are free to use, and have more than 1000 fonts to choose from.
Example Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Font Size and Style Demo</title>
<style>
body {
font-family: Arial, sans-serif; /* Default font */
}
.normal {
font-weight: normal; /* Inherits default font weight */
font-style: normal; /* Inherits default font style */
font-size: 1em; /* Default font size (relative to parent element) */
}
© Edunet Foundation. All rights reserved. | 77
.bold {
font-weight: bold; /* Makes the font bold */
}
.italic {
font-style: italic; /* Makes the font italic */
}
.large-font {
font-size: 1.5em; /* Increases the font size to 1.5 times the default */
}
.small-font {
font-size: 0.8em; /* Decreases the font size to 0.8 times the default */
}
</style>
</head>
<body>
<h1>Font Size and Style Examples</h1>
<p class="normal">This paragraph has a normal font size and style.</p>
<p class="bold">This paragraph is bold.</p>
<p class="italic">This paragraph is italic.</p>
<p class="large-font">This paragraph has a larger font size (1.5em).</p>
<p class="small-font">This paragraph has a smaller font size (0.8em).</p>
</body>
</html>
Output:
© Edunet Foundation. All rights reserved. | 78
1.5.7 CSS Position
CSS positioning allows you to control the layout of HTML elements using properties
such as top, right, bottom, and left. Understanding the different types of position
properties in CSS—static, relative, absolute, fixed, and sticky—can enhance the
design and functionality of web pages. This article explores these properties with
examples, illustrating how each can be applied to achieve various layout effects.
There are five different types of position properties available in CSS:
Position
Property Description
An element with position: fixed property remains in the same position
Fixed
relative to the viewport even when the page is scrolled.
Default positioning method. Elements with position: static are
Static
positioned according to the normal flow of the document.
Elements with position: relative are positioned relative to their normal
Relative position in the document flow. Other elements will not fill the gap left
by this element when adjusted.
Absolute Positioned concerning its nearest non-static ancestor. Elements
Position
Property Description
with position: absolute are taken out of the normal document flow.
Combines features of position: relative and position: fixed. The element
Sticky is treated as position: relative until it reaches a specifiedthreshold, then
it becomes position: fixed.
This table provides a concise overview of the different positioning methods and their
characteristics.
© Edunet Foundation. All rights reserved. | 79
Example 1: The below example illustrates the CSS positioning element by using
the position: fixed property.
Code:
<!DOCTYPE html>
<html>
<head>
<title> CSS Positioning Element</title>
<style> body {
margin: 0; padding: 20px;
font-family: sans-serif; background: #efefef;
}
.fixed {
position: fixed; background: coral; color: #ffffff;
padding: 30px; top: 50;
left: 10;
}
span {
padding: 5px;
border: 1px #ffffff dotted;
}
</style>
</head>
<body>
<div class="fixed">Fixed Positioning
<span>position: fixed;</span>
</div>
<pre>
Edunet Foundation is a social enterprise which was founded in 2015 and
focuses on bridging the academia-industry divide, enhancing student
employability, promoting innovation and creating an entrepreneurial ecosystem in
India.
Working primarily with emerging technologies, and striving to leverage them
to augment,
upgrade the knowledge ecosystem and equip the beneficiaries to become
contributors themselves, we work extensively to build a workforce with an IR 4.0
enabled career.
The organization has enjoyed Special Consultative Status with the Economic
and Social Council (ECOSOC)
of the United Nations since 2020. With a national footprint, EF’s programs,
online and instructor-led, benefit tens of thousands of learners every year.
Edunet Foundation is a social enterprise which was founded in 2015 and
© Edunet Foundation. All rights reserved. | 80
focuses on bridging the academia-industry divide, enhancing student
employability, promoting innovation and creating an entrepreneurial ecosystem in
India.
Working primarily with emerging technologies, and striving to leverage them
to augment,
upgrade the knowledge ecosystem and equip the beneficiaries to become
contributors themselves, we work extensively to build a workforce with an IR 4.0
enabled career.
The organization has enjoyed Special Consultative Status with the Economic
and Social Council (ECOSOC)
of the United Nations since 2020. With a national footprint, EF’s programs,
online and instructor-led, benefit tens of thousands of learners every year.
</pre>
</body>
</html>
Output:
© Edunet Foundation. All rights reserved. | 81
Example 2: The below example illustrates the CSS positioning element by using
the position: static property.
Code:
<!DOCTYPE html>
<html>
<head>
<title> CSS Positioning Element</title>
<style> body {
margin: 0; padding: 20px;
font-family: sans-serif; background: #efefef;
}
.static {
position: static; background:coral; color: #ffffff;
padding: 30px;
}
span {
padding: 5px;
border: 1px #ffffff dotted;
}
</style>
</head>
<body>
<div class="static"> Static Positioning
<span>position: static;</span>
</div>
<pre>
Edunet Foundation is a social enterprise which was founded in 2015 and
focuses on bridging the academia-industry divide, enhancing student
employability, promoting innovation and creating an entrepreneurial ecosystem in
India.
Working primarily with emerging technologies, and striving to leverage them
to augment,
upgrade the knowledge ecosystem and equip the beneficiaries to become
contributors themselves, we work extensively to build a workforce with an IR 4.0
enabled career.
The organization has enjoyed Special Consultative Status with the Economic
and Social Council (ECOSOC)
of the United Nations since 2020. With a national footprint, EF’s programs,
online and instructor-led, benefit tens of thousands of learners every year.
Edunet Foundation is a social enterprise which was founded in 2015 and
© Edunet Foundation. All rights reserved. | 82
focuses on bridging the academia-industry divide, enhancing student
employability, promoting innovation and creating an entrepreneurial ecosystem in
India.
Working primarily with emerging technologies, and striving to leverage them
to augment,
upgrade the knowledge ecosystem and equip the beneficiaries to become
contributors themselves, we work extensively to build a workforce with an IR 4.0
enabled career.
The organization has enjoyed Special Consultative Status with the Economic
and Social Council (ECOSOC)
of the United Nations since 2020. With a national footprint, EF’s programs,
online and instructor-led, benefit tens of thousands of learners every year.
</pre>
</body>
</html>
Output:
© Edunet Foundation. All rights reserved. | 83
Example 3: The below example illustrates the CSS positioning element by using
the position: relative property. In the below illustration, the top and left coordinates
of the div are each 100px.
Code:
<!DOCTYPE html>
<html>
<head>
<title>CSS Positioning Element</title>
<style>
body {
margin: 0;
padding: 20px;
font-family: sans-serif;
background: #efefef;
}
.relative {
position: relative;
background: #cc0000;
color: #ffffff;
padding: 30px;
top: 100px;
left: 100px;
}
span {
padding: 5px;
border: 1px #ffffff dotted;
}
</style>
</head>
<body>
<div class="relative">
<pre>
Edunet Foundation is a social enterprise which was founded in 2015 and
focuses on bridging the academia-industry divide, enhancing student
employability, promoting innovation and creating an entrepreneurial ecosystem in
India.
Working primarily with emerging technologies, and striving to leverage them
to augment,
© Edunet Foundation. All rights reserved. | 84
upgrade the knowledge ecosystem and equip the beneficiaries to become
contributors themselves, we work extensively to build a workforce with an IR 4.0
enabled career.
The organization has enjoyed Special Consultative Status with the Economic
and Social Council (ECOSOC)
of the United Nations since 2020. With a national footprint, EF’s programs,
online and instructor-led, benefit tens of thousands of learners every year.
Edunet Foundation is a social enterprise which was founded in 2015 and
focuses on bridging the academia-industry divide, enhancing student
employability, promoting innovation and creating an entrepreneurial ecosystem in
India.
Working primarily with emerging technologies, and striving to leverage them
to augment,
upgrade the knowledge ecosystem and equip the beneficiaries to become
contributors themselves, we work extensively to build a workforce with an IR 4.0
enabled career.
The organization has enjoyed Special Consultative Status with the Economic
and Social Council (ECOSOC)
of the United Nations since 2020. With a national footprint, EF’s programs,
online and instructor-led, benefit tens of thousands of learners every year.
</pre>
</div>
</body>
</html>
Output:
© Edunet Foundation. All rights reserved. | 85
Example 4: The below example illustrates the CSS positioning element by using
the position: absolute property.
Code:
<!DOCTYPE html>
<html>
<head>
<title> CSS Positioning Element</title>
<style> body {
margin: 0; padding: 20px;
font-family: sans-serif; background: #efefef;
}
.absolute {
position: absolute;
background: teal; color: #ffffff;
padding: 30px; font-size: 15px; bottom: 20px; right: 20px;
}
.relative {
position: relative; background: thistle; height: 300px;
font-size: 30px;
border: 1px solid white; text-align: center;
}
span {
padding: 5px;
border: 1px #ffffff dotted;
}
pre {
padding: 20px;
border: 1px solid white;
}
</style>
</head>
<body>
<pre>
Edunet Foundation is a social enterprise which was founded in 2015 and
focuses on bridging the academia-industry divide, enhancing student
employability, promoting innovation and creating an entrepreneurial ecosystem in
India.
Working primarily with emerging technologies, and striving to leverage them to
augment,
upgrade the knowledge ecosystem and equip the beneficiaries to become
contributors themselves, we work extensively to build a workforce with an IR 4.0
enabled career.
© Edunet Foundation. All rights reserved. | 86
The organization has enjoyed Special Consultative Status with the Economic and
Social Council (ECOSOC)
of the United Nations since 2020. With a national footprint, EF’s programs,
online and instructor-led, benefit tens of thousands of learners every year.
<div class="relative">
<div >
Position Relative
</div>
<div class="absolute"> Position Absolute
</div>
</div>
</body>
</html>
Output:
CSS positioning is essential for creating responsive and visually appealing web
designs. By utilizing properties like position: static, relative, absolute, fixed, and sticky,
developers can precisely control the placement and behavior of HTML elements on a
webpage. Experimenting with these properties can lead to innovative and dynamic
CSS layouts, improving the user experience in web design.
1.5.8 CSS List
The List in CSS specifies the listing of the contents or items in a particular manner i.e.,
it can either be organized orderly or unorder way, which helps to make a clean
webpage. It can be used to arrange the huge with a variety of content as they are
flexible and easy to manage. The default style for the list is borderless.
The list can be categorized into 2 types:
Unordered List: In unordered lists, the list items are marked with bullets i.e.
small black circles by default.
© Edunet Foundation. All rights reserved. | 87
Ordered List: In ordered lists, the list items are marked with numbers and an
alphabet.
We have the following CSS lists properties, which can be used to control the CSS
lists:
list-style-type: This property is used to specify the appearance (such as disc,
character, or custom counter style) of the list item marker.
list-style-image: This property is used to set the images that will be used as
the list item marker.
list-style-position: It specifies the position of the marker box with respect to
the principal block box.
list-style: This property is used to set the list style.
1.5.9 CSS Table
<table> element was the only possible avenue for creating rich design layouts on the
Web. But creating layout with <table> was not its intended or ideal use. Now that better
layout options are available, developers can use the <table> element for presenting
tabular data as intended, much like a spreadsheet. This allows for semantic HTML, or
using HTML elements in alignment with their intended meaning.
1.5.10 Pseudo-elements
A pseudo-element is like adding or targeting an extra element without having to add
more HTML.
Syntax:
selector::pseudo-element {
property: value;
}
There are many Pseudo Elements in CSS but the ones which are most commonly
used are as follows:
::first-line: ::first-line Pseudo-element applies styles to the first line of a block-
level element. Note that the length of the first line depends on many factors,
including the width of the element, the width of the document, and the font size
of the text. Note that only a few properties are applied for first-line pseudo-
element like font properties, color properties, background properties, word-
spacing, letter-spacing, text-decoration, vertical-align, text-transform, line-
height, clear, etc.
::first-letter: ::first-letter Pseudo-element applies styles to the first letter of the
first line of a block-level element, but only when not preceded by other content
(such as images or inline tables). Note that only a few properties are applied for
first-line pseudo-element like font properties, color properties, background
properties, word-spacing, letter-spacing, text-decoration, vertical-align, text-
© Edunet Foundation. All rights reserved. | 88
transform, line-height, clear, etc.
::before: ::before Pseudo-element creates a pseudo-element that is the first
child of the selected element. It is often used to add cosmetic content to an
element with the content property. It is inline by default.
::after: ::after Pseudo-element creates a pseudo-element that is the last child
of the selected element. It is often used to add cosmetic content to an element
with the content property. It is inline by default.
Example Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pseudo-Element Demo</title>
<style> body {
font-family: Arial, sans-serif;
}
p {
margin-bottom: 15px;
}
a {
text-decoration: none; /* Remove default underline */ color: black;
}
a:hover {
text-decoration: underline; /* Underline on hover */
}
q {
position: relative; /* Needed for pseudo-elements before and after */ padding:
5px;
border: 1px solid #ddd;
}
q:before {
content: "“"; /* Insert opening quotation mark */ position: absolute;
left: -10px; /* Adjust positioning as needed */
}
q:after {
content: "”"; /* Insert closing quotation mark */ position: absolute;
right: -10px; /* Adjust positioning as needed */
}
</style>
© Edunet Foundation. All rights reserved. | 89
</head>
<body>
<h1>Pseudo-Element Examples</h1>
<p>This paragraph demonstrates some pseudo-elements:</p>
<a href="#">This link has a hover effect on the underline.</a>
<q>This quote has a before and after pseudo-element for quotation marks.</q>
</body>
</html>
Output:
1.5.11 CSS Transformation
The transform property in CSS is used to change the coordinate space of the visual
formatting model. This is used to add effects like skew, rotate, translate, etc on
elements.
Syntax:
transform: none | transform-functions | initial | inherit;
Example code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS Transform Demo</title>
<style> body {
font-family: Arial, sans-serif;
}
.container { display: flex;
justify-content: space-around; width: 80%;
margin: 0 auto; padding: 20px;
}
.box {
width: 100px; height: 100px;
background-color: turquoise;
border: 12px outset #ccc; margin: 10px;
text-align: center;
© Edunet Foundation. All rights reserved. | 90
line-height: 100px; /* Center text vertically */
}
.transform-rotate {
transform: rotate(45deg); /* Rotate 45 degrees clockwise */
}
.transform-scale {
transform: scale(1.5); /* Scale to 1.5 times the size */
}
.transform-translate {
transform: translateX(50px) translateY(20px); /* Move 50px to the right and 20px
down */
}
.transform-skew {
transform: skewX(10deg) skewY(5deg); /* Skew along X and Y axes */
}
</style>
</head>
<body>
<h1>CSS Transform Examples</h1>
<div class="container">
<div class="box">Original</div>
<div class="box transform-rotate">Rotated</div>
<div class="box transform-scale">Scaled</div>
<div class="box transform-translate">Translated</div>
<div class="box transform-skew">Skewed</div>
</div>
</body>
</html>
Output:
© Edunet Foundation. All rights reserved. | 91
1.5.12 CSS Media Queries
The Media query in CSS is used to create a responsive web design. It means that
the view of a web page differs from system to system based on screen or media types.
The breakpoint specifies for what device-width size, the content is just starting to break
or deform.
Media queries can be used to check many things:
width and height of the viewport
width and height of the device
Orientation
Resolution
A media query consist of a media type that can contain one or more expression which
can be either true or false. The result of the query is true if the specified mediamatches
the type of device the document is displayed on. If the media query is true then a style
sheet is applied.
Syntax:
@media not | only mediatype and (expression) {
// Code content
}
Example Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Responsive Website Demo (Color Change)</title>
<style> body {
font-family: Arial, sans-serif; margin: 0;
}
.header {
background-color: #ddd; padding: 20px;
text-align: center;
color: #333; /* Default color */
}
.nav {
background-color: #ccc; padding: 10px;
}
.nav ul {
list-style: none; padding: 0;
margin: 0;
© Edunet Foundation. All rights reserved. | 92
text-align: center;
}
.nav li {
display: inline-block; margin-right: 20px;
}
.nav a {
text-decoration: none; color: black;
}
.main {
padding: 20px;
}
/* Media query for screens smaller than 768px */ @media screen and (max-width:
768px) {
.header {
font-size: 18px;
color: hotpink; /* Change color for smaller screens */
}
.nav {
display: flex;
flex-direction: column; align-items: center;
}
.nav li {
margin-right: 0;
margin-bottom: 10px;
color: teal; /* Change color for smaller screens */
}
}
</style>
</head>
<body>
<header class="header">
<h1>Responsive Website Demo</h1>
</header>
<nav class="nav">
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
© Edunet Foundation. All rights reserved. | 93
<main class="main">
<p>This is the main content of the website. It will respond to different screen
sizes.</p>
<p>This is some more content that will also respond to the screen size.</p>
</main>
</body>
</html>
Output:
Laptop View:
Mobile View:
1.5.13 CSS Grid
CSS Grid is a powerful tool that allows for two-dimensional layouts to be created on
the web.
The display: grid directive creates only a single-column grid container. Therefore, the
grid items will display in the normal layout flow (one item below another).
inline-grid tells browsers to display the selected HTML element as an inline-level grid
box model. In other words, setting an element's display property's value to inline-grid
turns the box model into an inline-level grid layout module.
© Edunet Foundation. All rights reserved. | 94
Example 1: Display Grid Property
This example illustrates the use of display: grid; property.
Example Code:
<!DOCTYPE html>
<html>
<head>
<style>
.grid-container { display: grid;
grid-template-columns: auto auto auto; background-color: rosybrown;
padding: 5px;
}
.grid-item {
background-color: rgba(255, 255, 255, 0.8); border: 12px inset hotpink;
border-radius: 25%;
padding: 20px; font-size: 30px; text-align: center;
}
</style>
</head>
<body>
<div class="grid-container">
<div class="grid-item">MOBILE</div>
<div class="grid-item">LAPTOP</div>
<div class="grid-item">ROUTER</div>
<div class="grid-item">SWITCHES</div>
<div class="grid-item">ADAPTER</div>
<div class="grid-item">CHARGER</div>
<div class="grid-item">POWERBANK</div>
<div class="grid-item">POWERCABLE</div>
<div class="grid-item">BLUETOOTH MOUSE</div>
</div>
</body>
</html>
Output:
© Edunet Foundation. All rights reserved. | 95
Example 2: Display inline-grid Property
This example illustrates the use of display:inline-grid; property.
Code:
<!DOCTYPE html>
<html>
<head>
<style>
.grid-container { display: inline-grid;
grid-template-columns: auto auto auto; background-color:slateblue;
padding: 5px;
color:white;
}
.grid-item {
background-color: midnightblue; border: 12px groove orangered;
padding: 20px; font-size: 30px;
color:white;
}
</style>
</head>
<body>
<div class="grid-container">
<div class="grid-item">MOBILE</div>
<div class="grid-item">LAPTOP</div>
<div class="grid-item">ROUTER</div>
<div class="grid-item">SWITCHES</div>
<div class="grid-item">ADAPTER</div>
<div class="grid-item">CHARGER</div>
<div class="grid-item">POWERBANK</div>
<div class="grid-item">POWERCABLE</div>
<div class="grid-item">BLUETOOTH MOUSE</div>
</div>
</center>
</body>
</html>
Output:
© Edunet Foundation. All rights reserved. | 96
We can control the gaps in the grid system using these items
grid-column-gap
grid-row-gap
grid-gap
Example 3: Custom Grid Gap
This example uses both grid-column-gap and grid-row-gap to define the custom
gap in grids.
Code:
<!DOCTYPE html>
<html>
<head>
<style>
/* Designing all grid */
.grid-container { display: grid;
grid-template-columns: auto auto auto; background-color: lightcoral;
grid-column-gap: 50px; grid-row-gap: 50px; padding: 5px;
}
/* Designing all grid-items */
.grid-item {
background-color: burlywood; border: 12px ridge khaki;
padding: 20px; font-size: 30px; text-align: center;
}
</style>
</head>
<body>
<!-- Creating grids -->
<div class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">6</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
<div class="grid-item">9</div>
</div>
</body>
</html>
© Edunet Foundation. All rights reserved. | 97
Output:
Note: Similarly grid-gap also works.
You can control individual grids using the following things on a grid system:
grid-column-lines
grid-row-lines
Example 4 : Custom Grid Lines
This code use both grid-column-lines and grid-row-lines together to display the
customised grid.
<!DOCTYPE html>
<html>
<head>
<style>
/* Designing all grid */
.grid-container { display: grid;
grid-template-columns: auto auto auto; grid-gap: 10px;
background-color: rgb(44, 215, 204); padding: 10px;
}
/* Designing all grid-items */
.grid-container>div {
background-color:lawngreen; text-align: center;
padding: 20px 0; font-size: 30px;
}
/* Grid Column */
.item1 {
grid-column-start: 1;
grid-column-end: 3;
}
/* Grid row */
.item3 {
grid-row-start: 2;
grid-row-end: 5;
© Edunet Foundation. All rights reserved. | 98
}
</style>
</head>
<body>
<div class="grid-container">
<div class="item1">Redmi</div>
<div class="item2">iphone</div>
<div class="item3">Samsung</div>
<div class="item4">Oppo</div>
<div class="item5">Zebronic</div>
<div class="item6">Logitech</div>
<div class="item7">Aura</div>
<div class="item8">Brands</div>
</div>
</body>
</html>
Output:
1.5.14 CSS FLEX
CSS Flexbox, short for Flexible Box Layout, offers a streamlined way to design
adaptable and visually appealing layouts. It works primarily in one dimension (row or
column) to intelligently distribute space among elements within a container, resulting
in clean alignment and responsive designs suitable for various screen sizes. Flexbox
is perfect for crafting both smaller components and overall webpage structures.
Features of flexbox:
High flexibility
Arrangement & alignment of items
Proper spacing
Order & sequencing of items
Bootstrap 4 is built on top of the flex layout
Before the Flexbox Model:
Block: Sections in web pages
Inline: Text
© Edunet Foundation. All rights reserved. | 99
Table: Two-dimensional table data
Positioned: Explicit position of an element
Flexbox Components:
Flex Container: The parent div containing various divisions.
Flex Items: The items inside the container div.
Figure 31. Flex Item
Image Source:
Creating a Flexbox:
To create a flexbox, set the display property of the container to flex.
Example Code:
<!DOCTYPE html>
<html>
<head>
<title>Flexbox Tutorial</title>
<style>
.flex-container {
display: flex;
background-color:lightpink;
}
.flex-container div { background-color: orchid; margin: 10px;
padding: 10px;
text-decoration:underline overline;
color:white;
font-size:30px;
}
</style>
</head>
<body>
<h4> Flexbox</h4>
<div class="flex-container">
<div>Audi</div>
<div>Toyota</div>
<div>BMW</div>
© Edunet Foundation. All rights reserved. | 100
<div>Honda</div>
<div>Ford</div>
<div>Hyundai</div>
<div>Kia</div>
<div>chevrolet</div>
</div>
</body>
</html>
Output:
Flexbox Axes:
Flexbox operates on two axes:
Main Axis: Runs from left to right by default.
Cross Axis: Perpendicular to the main axis, runs from top to bottom.
Figure 32. FlexBox Axes
1. Main Axis:
Main Start: The start of the main axis.
Main Size: The length between Main Start and Main End.
Main End: The endpoint of the main axis.
© Edunet Foundation. All rights reserved. | 101
2. Cross Axis:
The cross axis will be perpendicular to the main axis.
Cross Start: The start of the cross axis.
Cross Size: The length between Cross Start and Cross End.
Cross End: The endpoint of the cross axis.
Flex Direction Properties:
Left to Right: flex-direction: row;
Right to Left: flex-direction: row-reverse;
Top to Bottom: flex-direction: column;
Bottom to Top: flex-direction: column-reverse;
Aligning and Justifying Content:
Flexbox provides several properties for aligning and justifying content within the
container:
justify-content: Aligns items along the main axis (e.g., flex-start, flex-end,
center, space-between, space-around).
align-items: Aligns items along the cross axis (e.g., stretch, center, flex-start,
flex-end).
align-content: Aligns rows within a flex container when there is extra space
on the cross axis.
Responsive Design with Flexbox:
Flexbox excels in creating responsive designs by adjusting items to fit various screen
sizes. You can use media queries in combination with Flexbox properties to ensure
your layout adapts seamlessly to different devices.
© Edunet Foundation. All rights reserved. | 102
Example of Responsive Flexbox:
Code:
<!DOCTYPE html>
<html>
<head>
<title>Responsive Flexbox</title>
<style>
.flex-container {
display: flex; flex-wrap: wrap;
justify-content: space-around; background-color: mediumspringgreen;
}
.flex-container div { background-color: maroon; margin: 10px;
padding: 20px;
flex: 1 1 200px;
color:white;
}
@media (max-width: 600px) {
.flex-container {
flex-direction: column;
}
}
</style>
</head>
<body>
<h2>Responsive Flexbox</h2>
<div class="flex-container">
<div>MERN STACK</div>
<div>Artificial Intelligence</div>
<div>BlockChain</div>
<div>Generative AI</div>
<div>Robotics</div>
<div>Intenet of Behaviors</div>
</div>
</body>
</html>
Output:
CSS Flexbox is an essential tool for creating flexible and responsive web layouts. Its
ability to distribute space and align items effectively makes it a vital part of modern web
design.
© Edunet Foundation. All rights reserved. | 103
Chapter 2:Foundation: JavaScript Programming
Learning Outcomes:
Understand the fundamentals of JavaScript and its role in web
development.
Master the basic syntax and constructs of JavaScript.
Apply Object-Oriented Programming (OOP) principles to create
and manage complex code structures.
Understand and implement modules for better code
organization and reuse using ES6.
Work with APIs using the Fetch API to retrieve and manipulate
data from external sources.
2.1 Introduction to JavaScript
JavaScript is a scripting language for creating dynamic web page content. It
creates elements for improving site visitors’ interaction with web pages, such as
dropdown menus, animated graphics, and dynamic background colors.
Figure 33. Javascript event
Image Source: https://www.geeksforgeeks.org/javascript-events/
What Is JavaScript Used For?
JavaScript is used to make dynamic websites, web and mobile apps, games, web
servers, back-end infrastructures, and more.
© Edunet Foundation. All rights reserved. | 104
2.1.1 How to Use JavaScript in HTML
1. Inline JavaScript:
Here, you have the JavaScript code in HTML tags in some special JS-based attributes.
For example, HTML tags have event attributes that allow you to execute some code
inline when an event is triggered.
<button onclick="alert('You just clicked a button')">Click me!</button>
This is an example of inline JavaScript. The value of onclick can be some Match
calculation, a dynamic addition to the DOM – any syntax-valid JavaScript code.
2. Internal JavaScript, with the script tag
Just like the style tag for style declarations within an HTML page, the script tag exists
for JavaScript.
<script>
function(){
alert("I am inside a script tag")
}
</script>
3. External JavaScript
You may want to have your JavaScript code in a different file.
<!-- index.html -->
<script src="./script.js"></script>
// script.js
alert("I am inside an external file");
The src attribute of the script tag allows you to apply a source for the JavaScript code.
That reference is important because it notifies the browser to also fetch the content
of script.js.
script.js can be in the same directory with index.html, or it can be gotten from another
website. For the latter, you'll need to pass the full URL (https://.../script.js).
2.2 Syntax and basic constructs
JavaScript syntax refers to the rules and conventions dictating how code is structured
and arranged within the JavaScript programming language. This includes statements,
expressions, variables, functions, operators, and control flow constructs.
Syntax
console.log("Basic Print method in JavaScript");
© Edunet Foundation. All rights reserved. | 105
JavaScript syntax refers to the set of rules that determines how JavaScript
programs are constructed:
// Variable declaration
let c, d, e;
// Assign value to the variable
c = 5;
// Computer value of variables
d = c;
e = c / d;
2.2.1 JavaScript Values
There are two types of values defined in JavaScript Syntax:
Fixed Values: These are known as the literals.
Variable values: These are called variables
These are the features of JavaScript which have some predefined syntax:
JavaScript Literals
JavaScript Variables
JavaScript Operators
JavaScript Expressions
JavaScript Keywords
JavaScript Comments
JavaScript Data Types
JavaScript Functions
JavaScript Identifiers
2.2.2 JavaScript Literals
Syntax Rules for the JavaScript fixed values are:
JavaScript Numbers can be written with or without decimals.
Javascript Strings are text that can be written in single or double quotes.
Example Code:
//numbers
let num1 = 50
let num2 = 50.05
//strings
let str1 = "Edunet Foundation"
let str2 = 'Techsaksham Program'
console.log(num1)
console.log(num2)
console.log(str1)
console.log(str2)
© Edunet Foundation. All rights reserved. | 106
Output:
2.2.3 JavaScript Variables
A JavaScript variable is the simple name of the storage location where data is stored.
There are two types of variables in JavaScript which are listed below:
Local variables: Declare a variable inside of a block or function.
Global variables: Declare a variable outside function or with a window object.
Example: This example shows the use of JavaScript variables.
// Declare a variable and initialize it
// Global variable declaration
let Name = "MERN STACK CLOUD INTEGRATION";
// Function definition
function MyFunction() {
// Local variable declaration
let num = 45;
// Display the value of Global variable
console.log(Name);
// Display the value of local variable
console.log(num);
}
// Function call
MyFunction();
Output:
2.2.4 JavaScript Operators
JavaScript operators are symbols that are used to compute the value or in other
words, we can perform operations on operands. Arithmetic operators ( +, -, *, / ) are
used to compute the value, and Assignment operators ( =, +=, %= ) are used to assign
the values to variables.
© Edunet Foundation. All rights reserved. | 107
Example: This example shows the use of javascript operators.
// Variable Declarations
let x, y, sum;
// Assign value to the variables
x = 3;
y = 23;
// Use arithmetic operator to
// add two numbers
sum = x + y;
console.log(sum);
Output:
2.2.5 JavaScript Expressions
Javascript Expression is the combination of values, operators, and variables. It is used
to compute the values.
Example: This example shows a JavaScript expression.
// Variable Declarations
let x, num, sum;
// Assign value to the variables
x = 20;
y = 30
// Expression to divide a number
num = x / 2;
// Expression to add two numbers
sum = x + y;
console.log(num + "\n" + sum);
Output:
© Edunet Foundation. All rights reserved. | 108
2.2.6 JavaScript Keywords
The keywords are the reserved words that have special meanings in JavaScript.
// let is the keyword used to
// define the variable
let a, b;
// function is the keyword which tells
// the browser to create a function
function Edunet(){};
2.2.7 JavaScript Comments
The comments are ignored by the JavaScript compiler. It increases the readability of
code. It adds suggestions, Information, and warning of code. Anything written after
double slashes // (single-line comment) or between /* and */ (multi-line comment) is
treated as a comment and ignored by the JavaScript compiler.
Example: This example shows the use of javascript comments.
// Variable Declarations
let x, num, sum;
// Assign value to the variables
x = 20;
y = 30
/* Expression to add two numbers */
sum = x + y;
console.log(sum);
Output:
2.2.8 JavaScript Data Types
JavaScript provides different datatypes to hold different values on variables.
JavaScript is a dynamic programming language, which means do not need to specify
the type of variable. There are two types of data types in JavaScript.
Primitive data type
Non-primitive (reference) data type
// It store string data type
let txt = "EdunetFoundation-Techsaksham";
// It store integer data type
let a = 5;
let b = 5;
// It store Boolean data type
(a == b )
// To check Strictly (i.e. Whether the datatypes
© Edunet Foundation. All rights reserved. | 109
// of both variables are same) === is used
(a === b)---> returns true to the console
// It store array data type
let places= ["GFG", "Computer", "Hello"];
// It store object data (objects are
// represented in the below way mainly)
let Student = {
firstName: "Johnny",
lastName: "Diaz",
age: 35,
mark: "blueEYE"
}
2.2.9 JavaScript Functions
JavaScript functions are the blocks of code used to perform some particular
operations. JavaScript function is executed when something calls it. It calls many times
so the function is reusable.
Syntax:
function functionName( par1, par2, ....., parn ) {
// Function code
}
The JavaScript function can contain zero or more arguments.
Example: This example shows the use of Javascript functions.
// Function definition
function func() {
// Declare a variable
let num = 45;
// Display the result
console.log(num);
}
// Function call
func();
Output:
© Edunet Foundation. All rights reserved. | 110
2.2.10 JavaScript Identifiers
JavaScript Identifiers are names used to name variables and keywords and functions.
A identifier must begin with:
A letter(A-Z or a-z)
A dollar sign($)
A underscore(_)
Note: Numbers are not allowed as a first character in JavaScript Identifiers.
2.2.11 JavaScript Case Sensitive
JavaScript Identifiers are case-sensitive.
Example: Both the variables firstName and firstname are different from each other.
let firstName = "BlockChain Bitcoin";
let firstname = 100;
console.log(firstName);
console.log(firstname);
Output:
2.2.12 JavaScript Camel Case
In JavaScript Camel case is preferred to name a identifier.
Example:
let firstName
let lastName
2.2.13 JavaScript Character Set
A unicode character set is used in JavaScript. A unicode covers the characters,
punctuations and symbols.
2.3 Variables and data types
2.3.1 Variables and data types
Variables and data types are essential concepts in programming. In JavaScript, they
are used to store and manage data.
© Edunet Foundation. All rights reserved. | 111
Variables
var Keyword
The var keyword is used to declare a variable. It can be used throughout the function
or globally.
Example Code:
var x = 10;
var a = "Techsaksham Program Welcomes you all for MERN STACK Technology
";
var b = 10;
var c = 12;
var d = b + c;
console.log(a);
console.log(b);
console.log(c);
console.log(d);
Output:
let Keyword
The let keyword declares a variable that is limited to the block where it's defined. It's
useful for variables that may change.
let y = "Hello";
let a = "Hello learners";
let b = "joining";
let c = " 12";
let d = b + c;
console.log(a); // Output: Hello learners
console.log(b); // Output: joining
console.log(c); // Output: 12
console.log(d); // Output: joining 12
© Edunet Foundation. All rights reserved. | 112
const Keyword
The const keyword declares a variable that cannot be reassigned. It is also block-
scoped.
const PI = 3.14;
const a = "Hello learners";
console.log(a); // Output: Hello learners
const b = 400;
console.log(b); // Output: 400
const c = "12";
console.log(c); // Output: 12
// Cannot change the value of a const variable
// c = "new"; // This will cause an error
Data Types
JavaScript is a loosely typed language, meaning variables can hold any type of data.
There are eight basic data types.
Figure 34. Data Types
Image Source: https://medium.com/@rd893918/learn-javascript-with-me-iv-93b8c179fbbe
Primitive Data Types
1. Number: Numbers are stored in a 64-bit format. You don't need different
types for integers and floats.
let num = 42;
let price = 19.99;
© Edunet Foundation. All rights reserved. | 113
2. String: A sequence of characters.
let message = "Hello, World!";
3. Boolean: Represents true or false.
let isActive = true;
4. Null: Represents the intentional absence of any object value.
let emptyValue = null;
5. Undefined: A variable that has not been assigned a value.
let notAssigned;
6. Symbol: Provides unique identifiers.
let sym = Symbol('id');
7. BigInt: Used for numbers larger than the maximum safe integer.
let bigInt = 1234567890123456789012345678901234567890n;
Non-Primitive Data Types
The data types that are derived from primitive data types of the JavaScript
language are known as non-primitive data types. It is also known as derived data
types or reference data types.
Object: A collection of properties.
let person = {
name: 'Alice',
age: 25
};
2.4 Control Structures
JavaScript control structures are used to control the execution of a program based
on a specific condition. If the condition meets then a particular block of action will be
executed otherwise it will execute another block of action that satisfies that particular
condition.
© Edunet Foundation. All rights reserved. | 114
2.4.1 Conditional Statements
JavaScript conditional statements allow you to execute specific blocks of code based
on conditions. If the condition is met, a particular block of code will run; otherwise,
another block of code will execute based on the condition.
There are several methods that can be used to perform Conditional Statements in
JavaScript.
1. Using if Statement
The if statement is used to evaluate a particular condition. If the condition holds true,
the associated code block is executed.
Figure 35. If Statement
Image Source: https://dotnettutorials.net/lesson/javascript-conditional-statements/
Syntax:
if ( condition ) {
// If the condition is met,
//code will get executed.
© Edunet Foundation. All rights reserved. | 115
Example: In this example, we are using the if statement to find given number is even
or odd.
let num = 20;
if (num % 2 === 0) {
console.log("Given number is even number.");
}
if (num % 2 !== 0) {
console.log("Given number is odd number.");
};
Output
Explanation: This JavaScript code determines if the variable `num` is even or odd
using the modulo operator `%`. If `num` is divisible by 2 without a remainder, it logs
“Given number is even number.” Otherwise, it logs “Given number is odd number.”
2. Using if-else Statement
The if-else statement will perform some action for a specific condition. Here we are
using the else statement in which the else statement is written after the if statement
and it has no condition in their code block.
Figure 36. Conditional Statements
Image source : https://dotnettutorials.net/lesson/javascript-conditional-statements/
© Edunet Foundation. All rights reserved. | 116
Syntax:
if (condition1) {
// Executes when condition1 is true
else (condition2) {
// Executes when condition2 is true
Example: In this example, we are using if-else conditional statement to check the
driving licence eligibility date.
let age = 25;
if (age >= 18) {
console.log("You are eligible of driving licence")
} else {
console.log("You are not eligible for driving licence")
};
Output:
Explanation: This JavaScript code checks if the variable `age` is greater than or
equal to 18. If true, it logs “You are eligible for a driving license.” Otherwise, it logs
“You are not eligible for a driving license.” This indicates eligibility for driving based
on age.
3. Else if Statement
The else if statement in JavaScript allows handling multiple possible conditions and
outputs, evaluating more than two options based on whether the conditions are true
or false.
© Edunet Foundation. All rights reserved. | 117
Figure 37. IF else if
Image Source:- https://www.javascripttutorial.net/javascript-if-else-if/
Syntax:
if (1st condition) {
// Code for 1st condition
} else if (2nd condition) {
// ode for 2nd condition
} else if (3rd condition) {
// Code for 3rd condition
} else {
// ode that will execute if all
// above conditions are false
© Edunet Foundation. All rights reserved. | 118
Example: In this example, we are using the above-explained approach.
Code:
const num = 0;
if (num > 0) {
console.log("Given number is positive.");
} else if (num < 0) {
console.log("Given number is negative.");
} else {
console.log("Given number is zero.");
};
Output:
Explanation: This JavaScript code determines whether the constant `num` is
positive, negative, or zero. If `num` is greater than 0, it logs “Given number is
positive.” If `num` is less than 0, it logs “Given number is negative.” If neither
condition is met (i.e., `num` is zero), it logs “Given number is zero.”
4. Using Switch Statement (JavaScript Switch Case)
As the number of conditions increases, you can use multiple else-if statements in
JavaScript. but when we dealing with many conditions, the switch statement may be
a more preferred option.
Figure 38. Switch Statement
Image Source: https://dotnettutorials.net/lesson/javascript-conditional-statements/
© Edunet Foundation. All rights reserved. | 119
Syntax:
switch (expression) {
case value1:
statement1;
break;
case value2:
statement2;
break;
...
case valueN:
statementN;
break;
default:
statementDefault;
};
Example: In this example, we find a branch name Based on the student’s marks,
this switch statement assigns a specific engineering branch to the variable Branch.
The output displays the student’s branch name,
const Eligibilitymarks = 85;
let Courses;
switch (true) {
case Eligibilitymarks >= 90:
Courses = "MERN stack";
break;
case Eligibilitymarks >= 80:
Courses = "Artificial Intelligence";
break;
case Eligibilitymarks >= 70:
Courses = "CyberSecurity";
break;
case Eligibilitymarks >= 60:
© Edunet Foundation. All rights reserved. | 120
Courses = "Blockchain";
break;
case Eligibilitymarks >= 50:
Courses = "Power BI";
break;
default:
Courses = "Digital Literacy";
break;
}
console.log(`Student Course name is : ${Eligibilitymarks}`);
Output:
Explanation:
This JavaScript code assigns a branch of engineering to a student based on their
marks. It uses a switch statement with cases for different mark ranges. The student’s
branch is determined according to their marks and logged to the console.
5. Using Ternary Operator ( ?: )
The conditional operator, also referred to as the ternary operator (?:), is a shortcut
for expressing conditional statements in JavaScript.
Figure 39. Ternary Operator
Image Source: https://www.geeksforgeeks.org/conditional-or-ternary-operator-in-c/
Syntax:
condition ? value if true : value if false
© Edunet Foundation. All rights reserved. | 121
Example: In this example, we use the ternary operator to check if the user’s age is
18 or older. It prints eligibility for voting based on the condition.
let age = 21;
const result =
(age >= 18) ? "You are eligible to vote."
: "You are not eligible to vote.";
console.log(result);
Output:
Explanation: This JavaScript code checks if the variable `age` is greater than or
equal to 18. If true, it assigns the string “You are eligible to vote.” to the variable
`result`. Otherwise, it assigns “You are not eligible to vote.” The value of `result` is
then logged to the console.
2.4.2 Loops
JavaScript loops are essential for efficiently handling repetitive tasks. They execute a
block of code repeatedly as long as a specified condition remains true. These loops
are powerful tools for automating tasks and streamlining your code.
For example, suppose we want to print “Hello World” 5 times. This can be done
using JS Loop easily. In Loop, the statement needs to be written only once and the
loop will be executed 5 times as shown below:
for (let i = 0; i < 5; i++) {
console.log(" Iterating Loops concept");
}
Output:
© Edunet Foundation. All rights reserved. | 122
1. JavaScript for Loop
The JS for loop provides a concise way of writing the loop structure. The for loop
contains initialization, condition, and increment/decrement in one line thereby
providing a shorter, easy-to-debug structure of looping.
Syntax
for (initialization; testing condition; increment/decrement) {
statement(s)
Flowchart
Figure 40. For Loop
Image source: https://www.geeksforgeeks.org/loops-in-javascript/
Initialization condition: It initializes the variable and mark the start of a for
loop. An already declared variable can be used or a variable can be declared,
local to loop only.
Test Condition: It is used for testing the exit condition of a for loop. It must
return a boolean value. It is also an Entry Control Loop as the condition is
checked prior to the execution of the loop statements.
Statement execution: Once the condition is evaluated to be true, the
statements in the loop body are executed.
Increment/ Decrement: It is used for updating the variable for the next
iteration.
© Edunet Foundation. All rights reserved. | 123
Loop termination: When the condition becomes false, the loop terminates
marking the end of its life cycle.
Example
// JavaScript program to illustrate for loop
let x;
// for loop begins when x = 2
// and runs till x <= 4
for (x = 2; x <= 4; x++) {
console.log("Value of x: " + x);
}
Output
2. JavaScript while Loop
The JS while loop is a control flow statement that allows code to be executed
repeatedly based on a given Boolean condition. The while loop can be thought of as
a repeating if statement.
Syntax
while (boolean condition) {
loop statements...
© Edunet Foundation. All rights reserved. | 124
Flowchart
Figure 41. while Loop
Image source : https://www.geeksforgeeks.org/loops-in-javascript/
While loop starts with checking the condition. If it is evaluated to be true, then
the loop body statements are executed otherwise first statement following the
loop is executed. For this reason, it is also called the Entry control loop
Once the condition is evaluated to be true, the statements in the loop body
are executed. Normally the statements contain an updated value for the
variable being processed for the next iteration.
When the condition becomes false, the loop terminates which marks the end
of its life cycle.
Example
// JavaScript code to use while loop
let val = 1;
while (val < 6) {
console.log(val);
val += 1;
}
© Edunet Foundation. All rights reserved. | 125
Output
3. JavaScript do-while Loop
The JS do-while loop is similar to the while loop with the only difference is that it
checks for the condition after executing the statements, and therefore is an example
of an Exit Control Loop. It executes loop content at least once event the condition
is false.
Syntax
do {
Statements...
while (condition);
Flowchart
Figure 42. Do Loop
Image Source : https://www.geeksforgeeks.org/loops-in-javascript/
© Edunet Foundation. All rights reserved. | 126
The do-while loop starts with the execution of the statement(s). There is no
checking of any condition for the first time.
After the execution of the statements and update of the variable value, the
condition is checked for a true or false value. If it is evaluated to be true, the
next iteration of the loop starts.
When the condition becomes false, the loop terminates which marks the end
of its life cycle.
It is important to note that the do-while loop will execute its statements at least
once before any condition is checked and therefore is an example of the exit
control loop.
Example
let test = 1;
do {
console.log(test);
test++;
} while(test <= 5)
Output
2.5 Functions and Objects
What Are Functions?
Functions are like little machines in your code. You give them some input (called
arguments), and they do something with that input and give you back a result. This
makes your code more organized and reusable.
© Edunet Foundation. All rights reserved. | 127
How to Write Functions
1. Function Declaration: This is one way to create a function. You use the
function keyword, give your function a name, and then write what you want it
to do inside curly braces {}.
Code:
function greet(name) {
return `Hello, ${name}!`;
}
console.log(greet(Edunet Foundation!!!));
Output:
2. Function Expression: You can also create a function and save it in a
variable.
Code:
const greet = function(name) {
return `Welcome to learn about, ${name}!`;
};
console.log(greet('MERN STACK'));
Output:
3. Arrow Functions: A newer way to write functions, which is shorter and
cleaner.
const greet = (name) => `Pitch an idea to, ${name}!`;
console.log(greet('Complete Capstone Project')); //
Output:
© Edunet Foundation. All rights reserved. | 128
Function Parameters and Arguments
Parameters are like placeholders in your function. They wait for you to give
them values.
Arguments are the actual values you give to the function when you use it.
Code:
function add(a, b) {
return a + b;
}
console.log(add(5, 3));
Output:
In this example, a and b are parameters. When you call add(5, 3), 5 and 3 are
arguments.
What Are Objects?
Objects are like real-life objects. They have properties (things they have) and
methods (things they can do). In JavaScript, objects help you store and manage
data.
How to Create Objects
1. Object Literal: The simplest way to create an object.
const person = {
name: 'examples',
age: 25,
greet: function() {
return `Lets run through some ${this.name}`;
}
};
console.log(person.name);
console.log(person.age);
console.log(person.greet());
© Edunet Foundation. All rights reserved. | 129
Output:
2. Adding and Changing Properties: You can add new properties or change
existing ones.
person.job = 'Developer'; // Adding a new property
person.age = 26; // Changing an existing property
console.log(person.job); // Output: Developer
console.log(person.age); // Output: 26
Arrays
Arrays are special objects used to store multiple values in a single variable.
let fruits = ['Apple', 'Banana', 'Cherry'];
console.log(fruits[0]); // Output: Apple
console.log(fruits[1]); // Output: Banana
console.log(fruits[2]); // Output: Cherry
Methods
Objects can have methods, which are functions that belong to the object.
const calculator = {
add: function(a, b) {
return a + b;
},
subtract: function(a, b) {
return a - b;
}
};
console.log(calculator.add(5, 3)); // Output: 8
console.log(calculator.subtract(5, 3)); // Output: 2
2.6 Object Oriented Programming Concepts.
Classes
In JavaScript, a class is a blueprint for creating objects. A class encapsulates data
and functions that operate on that data.
© Edunet Foundation. All rights reserved. | 130
Declaring a Class
You can define a class using the class keyword.
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Take Up this course for free, That is nothing about
${this.name}`;
}
}
// Creating an instance of the class
const person1 = new Person('MERN STACK', 25);
console.log(person1.greet());
console.log(person1.age);
Output:
Objects
An object is an instance of a class. It contains properties and methods defined by the
class.
const person2 = new Person(Explore yourself in the age of, 30);
console.log(person2.greet());
console.log(person2.age);
JavaScript supports the four main principles of OOP: encapsulation, abstraction,
inheritance, and polymorphism. Here’s a brief explanation of each principle:
2.6.1 Encapsulation
Encapsulation is the concept of bundling data (properties) and methods (functions)
that operate on that data within a single unit, typically a class. It also involves
restricting access to some of the object's components, which helps prevent
unauthorized parts of the code from directly accessing and modifying the internal
state of the object.
© Edunet Foundation. All rights reserved. | 131
Example:
class Car {
#mileage; // Private property
constructor(brand, model) {
this.brand = brand;
this.model = model;
this.#mileage = 0; // Initializing private property
}
drive(distance) {
if (distance > 0) {
this.#mileage += distance;
}
}
getMileage() {
return this.#mileage;
}
}
// Creating instances of the Car class
const car1 = new Car('Toyota', 'Corolla');
const car2 = new Car('Honda', 'Civic');
// Driving the cars for some distance
car1.drive(50);
car2.drive(100);
// Getting and logging the mileage of the cars
console.log(`Car 1 (${car1.brand} ${car1.model}) mileage:
${car1.getMileage()} miles`);
console.log(`Car 2 (${car2.brand} ${car2.model}) mileage:
${car2.getMileage()} miles`);
Output:
In this example, the mileage property is private and can only be accessed or modified
using the methods provided ( drive and getMileage).
© Edunet Foundation. All rights reserved. | 132
2.6.2 Abstraction
Abstraction involves hiding the complex implementation details of a system and
exposing only the necessary parts. This makes it easier to interact with objects by
providing a simplified interface.
Example:
class CoffeeMachine {
#waterAmount; // Private property
constructor(power) {
this.power = power;
this.#waterAmount = 0;
}
addWater(amount) {
if (amount > 0) {
this.#waterAmount += amount;
}
}
#brewCoffee() { // Private method
console.log(`Brewing coffee with ${this.#waterAmount}ml water...`);
}
makeCoffee() {
if (this.#waterAmount > 0) {
this.#brewCoffee();
} else {
console.log('Please add water.');
}
}
}
class CoffeeMachine {
#waterAmount; // Private property
constructor(power) {
this.power = power;
this.#waterAmount = 0;
}
addWater(amount) {
if (amount > 0) {
this.#waterAmount += amount;
}
}
© Edunet Foundation. All rights reserved. | 133
#brewCoffee() { // Private method
console.log(`Brewing coffee with ${this.#waterAmount}ml water...`);
}
makeCoffee() {
if (this.#waterAmount > 0) {
this.#brewCoffee();
} else {
console.log('Please add water.');
}
}
}
Output:
Please add water.
Brewing coffee with 200ml water...
The internal details of how coffee is brewed are hidden from the user, who only
interacts with the addWater and makeCoffee methods.
2.6.3 Inheritance
Inheritance allows a class (subclass) to inherit properties and methods from another
class (superclass). This promotes code reusability and establishes a natural
hierarchy between classes.
Example:
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
speak() {
console.log(`${this.name} barks.`);
}
}
class Animal {
constructor(name) {
this.name = name;
}
© Edunet Foundation. All rights reserved. | 134
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
speak() {
console.log(`${this.name} barks.`);
}
}
Output:
Generic Animal makes a noise.
Buddy barks.
In this example, Dog inherits from Animal and overrides the speak method.
2.6.4. Polymorphism
Polymorphism allows objects of different classes to be treated as objects of a
common superclass. It enables a single action to behave differently based on the
object it is acting upon.
Example:
// Define the Shape, Circle, and Rectangle classes
class Shape {
area() {
return 0; // Default implementation
}
}
class Circle extends Shape {
constructor(radius) {
super();
this.radius = radius;
}
area() {
return Math.PI * this.radius * this.radius;
}
}
class Rectangle extends Shape {
constructor(width, height) {
super();
this.width = width;
this.height = height;
}
© Edunet Foundation. All rights reserved. | 135
area() {
return this.width * this.height;
}
}
// Create an array of shapes
const shapes = [
new Circle(5),
new Rectangle(10, 20)
];
// Calculate and log the area of each shape
shapes.forEach(shape => {
console.log(`The area is ${shape.area()}`);
});
Output:
The area is 78.53981633974483
The area is 200
Each shape class (Circle and Rectangle) provides its own implementation of the area
method.
2.7 DOM Manipulation
The HTML DOM (Document Object Model)
When a web page is loaded, the browser creates a Document Object Model of the page.
The HTML DOM model is constructed as a tree of Objects:
The HTML DOM Tree of Objects
Figure 43. DOM
Image Source: https://www.w3schools.com/js/js_htmldom.asp
© Edunet Foundation. All rights reserved. | 136
With the object model, JavaScript gets all the power it needs to create dynamic HTML:
JavaScript can change all the HTML elements in the page
JavaScript can change all the HTML attributes in the page
JavaScript can change all the CSS styles in the page
JavaScript can remove existing HTML elements and attributes
JavaScript can add new HTML elements and attributes
JavaScript can react to all existing HTML events in the page
JavaScript can create new HTML events in the page
What is the DOM?
The Document Object Model (DOM) is a programming interface for web documents.
It represents the page so that programs can change the document structure, style,
and content. The DOM is structured as a tree of objects (nodes), with the document
object at the top.
Why Manipulate the DOM?
Manipulating the DOM allows you to dynamically change the content, structure, and
style of a web page. This enables interactive and dynamic web applications.
Core Concepts
Nodes: The basic building blocks of the DOM. They can be elements, text, or
comments.
Elements: A type of node representing HTML tags.
Attributes: Properties of elements, such as id, class, and src.
2.7.1 Selecting Elements
Methods to Select Elements
1. getElementById
2. getElementsByClassName
3. getElementsByTagName
4. querySelector
5. querySelectorAll
Examples
// Select by ID
const elementById = document.getElementById('myId');
// Select by class name
const elementsByClassName = document.getElementsByClassName('myClass');
// Select by tag name
const elementsByTagName = document.getElementsByTagName('div');
// Select by CSS selector
const elementBySelector = document.querySelector('.myClass'); // single element
© Edunet Foundation. All rights reserved. | 137
const elementsBySelectorAll = document.querySelectorAll('.myClass'); // all matching elements
2.7.2 Modifying Elements
Changing Content
innerHTML: Changes the HTML inside an element.
textContent: Changes the text inside an element.
<!DOCTYPE html>
<html>
<body>
<h1>JavaScript HTML Events</h1>
<h2>The onclick Attribute</h2>
<h2 onclick="this.innerHTML='Ooops!'">Click on this text!</h2>
</body>
</html>
Output:
Before onclick
After OnClick
© Edunet Foundation. All rights reserved. | 138
Changing Attributes
setAttribute
getAttribute
RemoveAttribute
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<div id="myId"></div>
<script>
const element = document.getElementById('myId');
element.setAttribute('class', 'newClass');
const className = element.getAttribute('class');
console.log('Class name after setting attribute:', className); // Output: 'newClass'
element.removeAttribute('class');
const classAfterRemoval = element.getAttribute('class');
console.log('Class name after removing attribute:', classAfterRemoval); // Output: null
</script>
© Edunet Foundation. All rights reserved. | 139
</body>
</html>
Output:
Changing Styles
<!DOCTYPE html>
<html>
<head>
<title>Style Test</title>
</head>
<body>
<div id="myId">Sample Text</div>
<script>
const element = document.getElementById('myId');
element.style.color = 'blue';
element.style.backgroundColor = 'yellow';
element.style.fontSize = '20px';
</script>
</body>
</html>
Output:
© Edunet Foundation. All rights reserved. | 140
2.7.3 Creating and Removing Elements
Creating Elements
document.createElement
document.createTextNode
appendChild
insertBefore
; <!DOCTYPE html>
<html>
<head>
<title>DOM Manipulation</title>
</head>
<body>
<div id="myId">Sample Text</div>
<script>
// Create a new element
const newElement = document.createElement('div');
newElement.textContent = 'Hello, world!';
// Create a text node (not used later in the script)
const newText = document.createTextNode('This is a text node.');
// Append new element to the DOM
document.body.appendChild(newElement);
// Insert new element before another element
const referenceElement = document.getElementById('myId');
document.body.insertBefore(newElement, referenceElement);
</script>
</body>
</html>
© Edunet Foundation. All rights reserved. | 141
Output:
Removing Elements
removeChild
Remove
<!DOCTYPE html>
<html>
<head>
<title>DOM Manipulation</title>
</head>
<body>
<div id="parentId">
<div id="childId">Child Element</div>
</div>
<script>
const parentElement = document.getElementById('parentId');
const childElement = document.getElementById('childId');
// Remove child element using removeChild
parentElement.removeChild(childElement);
// Alternative method to remove the child element (this will have no effect since the element is
already removed)
// childElement.remove();
© Edunet Foundation. All rights reserved. | 142
</script>
</body>
</html>
Output:
2.7.4 Event Handling
Adding Event Listeners
addEventListener
Event Object
<!DOCTYPE html>
<html>
<head>
<title>Button Click Event</title>
</head>
<body>
<button id="myButton">Click Me</button>
<script>
const button = document.getElementById('myButton');
button.addEventListener('click', function(event) {
alert('Button was clicked!');
console.log(event); // Event object
});
© Edunet Foundation. All rights reserved. | 143
</script>
</body>
</html>
Output Before OnClick
Output After OnClick
Removing Event Listeners
RemoveEventListener
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width,
initial-scale=1.0">
<title>Document</title>
</head>
© Edunet Foundation. All rights reserved. | 144
<body>
<button id="clickIt">Click here</button>
<br>
<b id="effect"></b>
<script>
const x = document.getElementById("clickIt");
x.addEventListener("click", Respond);
function Respond(e) {
document.getElementById("effect").innerHTML +=
"Type of event triggered = " + e.type + "<br><br>";
document.getElementById("effect").innerHTML +=
"Now click Event is disabled !! " + "<br><br>";
x.innerText = "Click is disable !";
// The click event is only one time triggered
// by clicking the "click here" button.
x.removeEventListener("click", Respond);
</script>
<body>
</html>
Output Before Onclick:
© Edunet Foundation. All rights reserved. | 145
Output After Onclick:
Common Events
Mouse Events: click, dblclick, mouseover, mouseout, mousedown, mouseup
Keyboard Events: keydown, keyup, keypress
Form Events: submit, change, focus, blur
Window Events: load, resize, scroll
2.8 Introduction to ES6
ES6 or ECMAScript 2015 is the 6th version of the ECMAScript programming
language. ECMAScript is the standardization of Javascript which was released in 2015
and subsequently renamed as ECMAScript 2015.
ECMAScript and Javascript are both different.
ECMAScript vs Javascript
ECMAScript: It is the specification defined in ECMA-262 for creating a general-
purpose scripting language. In simple terms, it is a standardization for creating a
scripting language. It was introduced by ECMA International and is an implementation
with which we learn how to create a scripting language.
Javascript: A general-purpose scripting language that confirms the ECMAScript
specification. It is an implementation that tells us how to use a scripting language.
ES6
Javascript ES6 has been around for a few years now, and it allows us to write code in
a clever way which basically makes the code more modern and more readable. It’s
fair to say that with the use of ES6 features we write less and do more, hence the term
‘write less, do more’ definitely suits ES6.
ES6 introduced several key features like const, let, arrow functions, template literals,
default parameters, and a lot more. Let’s take a look at them one by one.
© Edunet Foundation. All rights reserved. | 146
2.8.1 const
The const keyword is used to declare constant variables whose values can’t be
changed. It is an immutable variable except when used with objects.
Example: The below example will explain you the use of const keyword in different
situations.
// Const
const name = 'Mukul';
console.log(name);
// Will print 'Mukul' to the console.
// Trying to reassign a const variable
name = 'Rahul';
console.log(name);
// Will give TypeError.
// Trying to declare const variable first
// and then initialise in another line
const org_name;
org_name = " use edunetfoundation word ";
console.log(org_name);
// Throws an syntax error: missing initializer in const declaration
2.8.2 let
The let variables are mutable i.e. their values can be changed. It works similar to the
var keyword with some key differences like scoping which makes it a better option
when compared to var.
Example: This example will illustrate how to declare varibale using the let keyword.
javascript
// let
let name = 'Mukul';
console.log(name);
// Prints Mukul
name = 'Rahul';
console.log(name);
// Prints Rahul
// Trying to declare let variable first and then initialise in another line
let org_name;
org_name = " use edunetfoundation word ";
© Edunet Foundation. All rights reserved. | 147
console.log(org_name);
// Prints use edunetfoundation word
Output
Mukul
Rahul
use edunetfoundation word
2.8.3 Arrow functions
Arrow functions are a more concise syntax for writing function expressions. These
function expressions make your code more readable, and more modern.
Example: The below example will show you how the arrow functions can be created
and implemented.
// Function declaration using function keyword
function simpleFunc(){
console.log("Declared using the function keyword");
}
simpleFunc();
// Function declared using arrow functions
const arrowFunc = () => {
console.log("Declared using the arrow functions");
}
arrowFunc();
Output
Declared using the function keyword
Declared using the arrow functions
2.8.4 Template literal
It allows us to use the JavaScript variables with the string without using
the ‘+’ operator. Template literal defined using (“) quotes.
Example: This example will explain the practical use of template literals.
javascript
// Without Template Literal
var name = ' use edunetfoundation word ';
console.log('Printed without using Template Literal');
console.log('My name is '+ name);
© Edunet Foundation. All rights reserved. | 148
// With Template Literal
const name1 = ' use edunetfoundation word ';
console.log('Printed by using Template Literal');
console.log(`My name is ${name1}`);
Output
Printed without using Template Literal
My name is use edunetfoundation word
Printed by using Template Literal
My name is use edunetfoundation word
Object and Array Desctructuring
Destructing in javascript basically means the breaking down of a complex
structure(Objects or arrays) into simpler parts. With the destructing assignment, we
can ‘unpack’ array objects into a bunch of variables.
Example: The below example will explain how the destructuring can be done in ES6.
// Object Destructuring
const college = {
name : 'DTU',
est : '1941',
isPvt : false
};
let {name, est, isPvt} = college;
console.log(name, est, isPvt);
// Array Destructuring
const arr = ['lionel', 'messi', 'barcelona'];
let[value1,value2,value3] = arr;
console.log(value1, value2, value3);
Output
DTU 1941 false
lionel messi barcelona
Default Parameters
In ES6, we can declare a function with a default parameter with a default value.
Example: This example will show how to define default paramters for a function.
javascript
© Edunet Foundation. All rights reserved. | 149
function fun(a, b=1){
return a + b;
}
console.log(fun(5,2));
console.log(fun(3));
Output
7
4
Classes
ES6 introduced classes in JavaScript. Classes in javascript can be used to create new
Objects with the help of a constructor, each class can only have one constructor inside
it.
Example: The below example will show how to create classes in ES6.
javascript
// classes in ES6
class Vehicle{
constructor(name,engine){
this.name = name;
this.engine = engine;
}
}
const bike1 = new Vehicle('Ninja ZX-10R','998cc');
const bike2 = new Vehicle('Duke','390cc');
console.log(bike1.name); // Ninja ZX-10R
console.log(bike2.name); // Duke
Output
Ninja ZX-10R
Duke
Rest parameter and spread operator
Rest Parameter: It is used to represent a number of parameter in an array to pass
them together to a function.
Example: This example will illustrate the practical use of the Rest paramter.
// ES6 rest parameter
function fun(...input){
let sum = 0;
for(let i of input){
sum += i;
© Edunet Foundation. All rights reserved. | 150
}
return sum;
}
console.log(fun(1,2)); // 3
console.log(fun(1,2,3)); // 6
console.log(fun(1,2,3,4,5)); // 15
Output
3
6
15
Spread Operator: It simply changes an array of n elements into a list of n different
elements.
Example: The below example will explain the practical implementation of the Spread
Operator.
// Spread operator
let arr = [1,2,3,-1];
console.log(...arr);
console.log(Math.max(...arr)); // -1
Output
1 2 3 -1
3
for/of Loop
The for/of loop allows you to iterate through the iterable items but in a short syntax as
compared to other loops.
Example: The for/of loop is implemented in the below code example with an array.
Javascript
const myArr = [5, 55, 33, 9, 6]
for(let element of myArr){
console.log(element);
}
Output
5
55
33
9
6
© Edunet Foundation. All rights reserved. | 151
JavaScript Maps and Sets:
Map: The maps in JavaScript are used to store multiple items in the form of key-value
pairs. The keys of a map can be of any datatype.
Set: A set consist of only unique value, a value can be stored only once in a set. It
can store any value of any datatype.
Example: The below example will explain the use of both the JavaScript Map and Set
practically.
Javascript
// Maps in JavaScript
const myMap = new Map([
["stringKey", 23],
[48, "numberedKey"]
]);
myMap.set(false, 0);
myMap.set(1, true);
console.log(myMap.get("stringKey"),
myMap.get(48), myMap.get(false),
myMap.get(1));
// Sets in JavaScript
const mySet =
new Set(["string value", "string value"]);
mySet.add(24);
mySet.add(24);
mySet.add(3);
console.log(mySet);
Output
23 numberedKey 0 true
Set(3) { 'string value', 24, 3 }
Promises
JavaScript promises are used to perform the asynchronous tasks, that takes some
time to get executed. It combines the synchronous and asynchronous code together.
Example: The below example will show how you can create and implement a promise
in JavaScript.
const JSpromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Promise is Working")
© Edunet Foundation. All rights reserved. | 152
}, 2000);
});
JSpromise.then((value) => {console.log(value)});
Output
Promise is Working
Symbol
Symbol is a type of primitive data type intriduced in ES6. It is used to specify
the hidden identifiers that can not be directly accessed by any other code.
Example: The use of the Symbol data type is explained in the below code example.
const gfg = {
name: " use edunetfoundation word ",
desc: "A Computer Science portal for all use edunetfoundation word "
}
let short_name = Symbol("short_name")
gfg.short_name = "GFG";
console.log(`${gfg.name}, \n${gfg.desc}`);
console.log(`Company's Short Name using gfg.short_name: ${gfg.short_name} `)
console.log(`Company's Short Name using gfg[short_name]: ${gfg[short_name]} `)
Output
use edunetfoundation word,
A Computer Science portal for all use edunetfoundation word
Company's Short Name using gfg.short_name: GFG
Company's Short Name using gfg[short_name]: undefined
String Methods
JavaScript startsWith(): This method will return true only if the testing string
starts with the passed or specified string.
JavaScript endsWith(): This mthod will return true, if the string ends with the
passes or specified string value.
JavaScript includes(): It will return true, if the testing string contains the
specified or passes value.
© Edunet Foundation. All rights reserved. | 153
Example: The below code example will illustrate the use of all the string methods
introduced in ES6.
// String startsWith()
const useStart = "This string implements the startsWith() method.";
console.log(useStart.startsWith("This string"),
useStart.startsWith("This is"));
// String endsWith()
const useEnd = "This string implements the endsWith() method.";
console.log(useEnd.endsWith("clear() method."),
useEnd.endsWith("method."));
// String includes()
const useIncludes = "This string implements the includes() method.";
console.log(useIncludes.includes("includes()"),
useIncludes.includes("My name"));
Output
true false
false true
true false
Array Methods
JavaScript Array.from(): It will return a array from any object which is iterable
and has the length property associated with it.
JavaScript Array.keys(): It returns an array of the iterator keys of the array.
JavaScript Array.find(): It will return the value of the first array element that
matches or passes the condition of the passed function.
JavaScript Array.findIndex(): It will return the index of the first array element
that matches or passes the condition of the passed function.
Example: The below code example implements all array methods introduced in ES6.
// Array.from() method
const newArr = Array.from("Edunet Foundation");
console.log("Implementing Array.from(): ", newArr)
// Array.keys() method
const milkProducts = ["Curd", "Cheese", "Butter", "Ice-Cream"];
const arrayKeys = milkProducts.keys();
console.log("Implementing Array.keys(): ")
for(let key of arrayKeys){
© Edunet Foundation. All rights reserved. | 154
console.log(key)
}
// Array.find() method
const findArray = ["clock", "strong", "planet", "earth"];
const lessThanSix = (item) => {
return item.trim.length < 6;
}
console.log("Implementing Array.find(): ",
findArray.find(lessThanSix));
console.log("Implementing Array.findIndex(): ",
findArray.findIndex(lessThanSix));
Output
Implementing Array.from(): [
'E', 'D', 'U', 'N',
'E', 'T', 'F', 'O',
'U', 'N', 'D', 'A',
'T' ‘I’ ‘O’ ‘N’
]
Object Enteries:
Object.entries() method is used to convert a single valued array into an array object
with a key-value pair as array items.
Example: The below example implements the object.entries() method practically.
const myArr =
[" edunetfoundation ", "A Computer Science Portal for all use edunetfoundation
word "];
const arr = myArr.entries()
for(let item of arr){
console.log(item);
}
Output
[ 0, ' edunetfoundation ' ]
[ 1, 'A Computer Science Portal for all use edunetfoundation word ' ]
© Edunet Foundation. All rights reserved. | 155
2.9 Asynchronous JavaScript and Working with APIs
2.9.1 Asynchronous JavaScript
Asynchronous JavaScript is a programming approach that enables the non-blocking
execution of tasks, allowing concurrent operations, improved responsiveness, and
efficient handling of time-consuming operations in web applications, JavaScript is a
single-threaded and synchronous language. The code is executed in order one at a
time, But Javascript may appear to be asynchronous in some situations.
There are several methods that can be used to perform asynchronous javascript tasks,
which are listed below:
Approach 1: Using callback
Callbacks are functions passed as arguments to be executed after an asynchronous
operation completes. They are used in asynchronous JavaScript to handle responses
and ensure non-blocking execution,
Syntax:
function myFunction(param1, param2, callback) {
// Do some work...
// Call the callback function
callback(result);
}
Example: In this example, the myFunction simulates an async task with a 3s delay. It
passes fetched data to the callback, which logs it. Output after 3s:
Javascript
function myFunction(callback) {
setTimeout(() => {
const data = { name: "Aman", age: 21 };
callback(data);
}, 3000);
}
myFunction((data) => {
console.log("Data:", data);
});
Output:
Data: { name: 'Aman', age: 21 }
© Edunet Foundation. All rights reserved. | 156
Approach 2: Using Promises
Promises are objects representing the eventual completion (or failure) of an
asynchronous operation, providing better handling of asynchronous code with .then()
and .catch().
Syntax:
let promise = new Promise(function(resolve, reject){
//do something
});
Example: In this example, The function mydata() returns a Promise that resolves with
data after a delay. The data is logged, or an error is caught if rejected, after 2 seconds.
Javascript
function mydata() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const data = { name: "Rohit", age: 23 };
resolve(data);
}, 2000);
});
}
mydata()
.then((data) => {
console.log("Data:", data);
})
.catch((error) => {
console.error("Error:", error);
});
Output:
Data: { name: 'Rohit', age: 23 }
2.9.2 Async and Await in JavaScript
Async and Await in JavaScript are powerful keywords used to handle asynchronous
operations with promises. Async functions implicitly return promises, while Await
pauses the execution until the promise is resolved. This simplifies asynchronous code
and enhances readability by making it appear synchronous.
Async Function
The async function allows us to write promise-based code as if it were synchronous.
This ensures that the execution thread is not blocked.
Promise Handling: Async functions always return a promise. If a value is
returned that is not a promise, JavaScript automatically wraps it in a resolved
promise.
© Edunet Foundation. All rights reserved. | 157
Async Syntax
async function myFunction() {
return "Hello";
}
Example: Here, we will see the basic use of async in JavaScript.
javascript
const getData = async () => {
let data = "Hello World";
return data;
}
getData().then(data => console.log(data));
Output
Hello World
Await Keyword:
The await keyword is used to wait for a promise to resolve. It can only be used within
an async block.
Execution Pause: Await makes the code wait until the promise returns a result,
allowing for cleaner and more manageable asynchronous code.
Syntax
let value = await promise;
Example : This example shows the basic use of the await keyword in JavaScript.
javascript
const getData = async () => {
let y = await "Hello World";
console.log(y);
}
console.log(1);
getData();
console.log(2);
Output
1
2
Hello World
The async keyword transforms a regular JavaScript function into an asynchronous
function, causing it to return a Promise.
The await keyword is used inside an async function to pause its execution and wait
for a Promise to resolve before continuing.
© Edunet Foundation. All rights reserved. | 158
Async/Await Example
Here, we will be implementing several promises in a method, and then that method
we will use for displaying our result. You can check the JS async/await syntax in the
example.
function asynchronous_operational_method() {
let first_promise =
new Promise((resolve, reject) => resolve("Hello"));
let second_promise =
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(" edunetfoundation.");
}, 1000);
});
let combined_promise =
Promise.all([first_promise, second_promise]);
return combined_promise;
}
async function display() {
let data = await asynchronous_operational_method();
console.log(data);
}
display();
Output:
[ 'Hello', ' edunetfoundation.' ]
Explanation:
1. Promise Creation:
Two promises are created: one resolve immediately with “Hello”, and the
other resolves after 1 second with ” edunetfoundation.”.
2. Combining Promises:
The Promise.all() method combines both promises into a single promise,
combined_promise.
3. Asynchronous Function:
The display() function is declared as async, indicating it contains
asynchronous operations.
4. Awaiting Promise Resolution:
The await keyword pauses execution until combined_promise is
resolved.
5. Logging Result:
The resolved array from combined_promise is logged to the console.
Note
To resolve and reject are predefined arguments by JavaScript.
resolve function is used when an asynchronous task is completed and returns
the result.
reject function is used when an asynchronous task fails and returns reasons for
failure.
© Edunet Foundation. All rights reserved. | 159
Advantages of Async and Await
1. Improved Readability: Async and Await allow asynchronous code to be written
in a synchronous style, making it easier to read and understand.
2. Error Handling: Using try/catch blocks with async/await makes error handling
straightforward.
3. Avoids Callback Hell: Async and Await help in avoiding nested callbacks and
complex promise chains.
4. Better Debugging: Debugging async/await code is more intuitive as it behaves
like synchronous code.
Conclusion
Async and Await in JavaScript have revolutionized asynchronous programming by
making code more readable and maintainable. By allowing asynchronous code to be
written in a synchronous style, they reduce the complexity associated with callbacks
and promise chaining. Understanding and using async and await effectively can
significantly enhance your JavaScript programming skills, making it easier to handle
asynchronous operations in your projects.
2.9.3 How to use JavaScript Fetch API to Get Data?
An API (Application Programming Interface) is a set of rules, protocols, and tools that
allows different software applications to communicate with each other.
One of the popular ways to perform API requests in JavaScript is by using Fetch API.
Fetch API can make GET and POST requests, JavaScript’s Fetch API is a powerful
tool for developers seeking to retrieve this data efficiently. This guide focuses on using
Fetch API to master the art of “GET” requests, the essential method for gathering
information from APIs.
What is the JavaScript Fetch API?
The Fetch API provides an interface for fetching resources (like JSON data) across
the web. It offers a more powerful and flexible alternative to traditional
XMLHttpRequest.
Key features of the Fetch API:
Promise-based: Simplifies asynchronous operations with JavaScript
promises.
Cleaner syntax: Uses the fetch() function for intuitive request handling.
Streamlined requests: Supports headers, methods, and body types for
customization.
Modern features: Includes streaming responses and CORS support.
Browser compatibility: Widely supported across major browsers
.
How to Use the JavaScript Fetch API
JavaScript fetch API uses the fetch() function at its core. The fetch method takes one
mandatory argument- the URL of the resource that you want to get. It also accepts
optional parameters like HTTP method, headers, body, and more.
Syntax:
fetch(url [, options])
.then(response => { // Handle the response })
.catch(error => { // Handle any errors });
© Edunet Foundation. All rights reserved. | 160
Learn more on how to use fetch API
Using Fetch API to Get Data
To Get data using the Fetch API in JavaScript, we use the fetch() function with the
URL of the resource we want to fetch. By default, the fetch method makes the Get
request.
Example: Get Data using Fetch API in JavaScript
The below examples show how to fetch data from a URL using JavaScript fetch API.
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
console.log('Data received:', data);
})
.catch(error => {
console.error('There was a problem with the fetch operation:', error);
});
Explanation:
1. fetch() Function: Initiates an HTTP request to the specified URL
(‘https://api.example.com/data’).
2. Response Handling:
.then(response => {…}): Handles the response received from the server.
if (!response.ok) {…}: Checks if the response was successful (status
code 200-299). If not, it throws an error.
return response.json(): Parses the response body as JSON and returns
it.
3. Data Processing:
.then(data => {…}): Handles the parsed JSON data received from the
server.
console.log(‘Data received:’, data): Logs the received data to the
console.
4. Error Handling:
.catch(error => {…}): Catches any errors that occur during the fetch
operation (e.g., network issues or failed requests).
console.error(‘There was a problem with the fetch operation:’, error):
Logs the error message to the console.
Making a Post request
POST requests are used to send data to a server. This is commonly used when
submitting forms or sending data to create a new resource. To use the JavaScript
Fetch API to post data to a server, you can make a POST request with the desired
data and handle the response.
© Edunet Foundation. All rights reserved. | 161
Example: Post Data using Fetch API in JavaScript
Here, let’s assume we want to create a new user by sending data to an API endpoint
located at https://api.example.com/users. We specify this endpoint as the target URL
for our POST request.
Within the fetch options, we set the method property to ‘POST’ to indicate that this
is a POST request. Additionally, we include the headers property to specify that we
are sending JSON data in the request body. The body of the request contains the user
data, which is converted to JSON format using JSON.stringify().
// Data to be sent in the POST request (in JSON format)
const postData = {
username: 'exampleUser',
email: '
[email protected]'
};
// POST request options
const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(postData)
};
// Make the POST request
fetch('https://api.example.com/users', requestOptions)
.then(response => {
// Check if the request was successful
if (!response.ok) {
throw new Error('Network response was not ok');
}
// Parse the JSON response
return response.json();
})
.then(data => {
// Handle the data returned from the server
console.log('Post request response:', data);
})
.catch(error => {
// Handle any errors that occurred during the fetch
console.error('There was a problem with the fetch operation:', error);
});
Explanation:
1. We define the data to be sent in the POST request, which is an object
containing a username and email.
2. We specify the options for the POST request, including the HTTP method
(POST), request headers (Content-Type: application/json), and request body
(the postData object converted to JSON using JSON.stringify()).
© Edunet Foundation. All rights reserved. | 162
3. We use the fetch() function to make a POST request to the specified URL
(https://api.example.com/users) with the request options.
4. We handle the response using .then() and check if it’s successful by accessing
the response.ok property. If the response is okay, we parse the JSON response
using response.json().
5. Once the JSON data is retrieved, we can then handle it accordingly.
6. Any errors that occur during the fetch operation are caught and handled using
.catch().
Error Handling
When working with the Fetch API, a robust error-handling strategy is crucial,
particularly for POST requests involving sensitive data. Utilize a try/catch block to
encapsulate your code, with the catch() method to manage errors.
Example: Error handling in Fetch API
Below is an example how how to handle errors while using fetch API.
try {
const response = await fetch('https://api.example.com/data', {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
}
});
if (!response.ok) {
throw new Error('Network response was not ok');
}
const result = await response.json();
console.log('Response:', result);
} catch (error) {
console.error('Error:', error);
}
Explanation:
The code uses a try/catch block to handle errors during a POST request using the
Fetch API. It sends data to ‘https://api.example.com/data’, with JSON formatting. If the
response is not successful, it throws an error. The catch block logs any errors
encountered during the process.
© Edunet Foundation. All rights reserved. | 163
Chapter 3: Leveraging Git Hub for Web Applications
Learning Outcomes:
Getting Started with GitHub for Web Projects.
Understanding GitHub for project development and
repository creation.
Leveraging GitHub Co-Pilot for AI-Assisted Coding.
3.1 Getting Started with GitHub for Web Projects.
3.1.1 Git basics
Git is a free and open-source version control system, originally created by Linus
Torvalds in 2005. Unlike older centralized version control systems such as SVN
and CVS, Git is distributed: every developer has the full history of their code
repository locally. This makes the initial clone of the repository slower, but
subsequent operations such as commit, blame, diff, merge, and log dramatically
faster.
Git also has excellent support for branching, merging, and rewriting repository
history, which has led to many innovative and powerful workflows and tools. Pull
requests are one such popular tool that allows teams to collaborate on Git
branches and efficiently review each other's code. Git is the most widely used
version control system in the world today and is considered the modern standard
for software development.
How Git works
Here is a basic overview of how Git works:
1. Create a "repository" (project) with a git hosting tool (like Bitbucket)
2. Copy (or clone) the repository to your local machine
3. Add a file to your local repo and "commit" (save) the changes
4. "Push" your changes to your main branch
5. Make a change to your file with a git hosting tool and commit
6. "Pull" the changes to your local machine
7. Create a "branch" (version), make a change, commit the change
8. Open a "pull request" (propose changes to the main branch)
9. "Merge" your branch to the main branch
3.1.2 How to Install Git on Windows
To use Git, you have to install it on your computer. Even if you have already installed
Git, it's probably a good idea to upgrade it to the latest version. You can either install
it as a package or via another installer or download it from its official site.
Now the question arises that how to download the Git installer package. Below is the
stepwise installation process that helps you to download and install the Git.
How to download Git?
Step1
© Edunet Foundation. All rights reserved. | 164
To download the Git installer, visit the Git's official site and go to download page. The
link for the download page is https://git-scm.com/downloads . The page looks like as
Figure 44. Git Install
Image Source: Git - Downloads (git-scm.com)
Click on the package given on the page as download 2.23.0 for windows. The
download will start after selecting the package.
Now, the Git installer package has been downloaded.
Install Git
Step2
Click on the downloaded installer file and select yes to continue. After the
selecting yes the installation begins, and the screen will look like as
© Edunet Foundation. All rights reserved. | 165
Figure 45. Setup Installation
Image Source: Git - Downloads (git-scm.com)
Click on next to continue.
Step3
Click next to continue.
Step4
The default Git command-line options are selected automatically. You can choose
your preferred choice. Click next to continue.
Default components are automatically selected in this step. You can also choose
your required part.
Figure 46. Select Components
© Edunet Foundation. All rights reserved. | 166
Figure 47. Adjusting PATH environment
Step5
The default transport backend options are selected in this step. Click next to
continue.
Figure 48. Choose HTTPS transport backend
© Edunet Foundation. All rights reserved. | 167
Step6
Select your required line ending option and click next to continue.
Figure 49. Configuration line ending Options
Step7
Select preferred terminal emulator clicks on the next to continue.
Figure 49. Configuring the terminal
© Edunet Foundation. All rights reserved. | 168
Step8
This is the last step that provides some extra features like system caching, credential
management and symbolic link. Select the required features and click on
the next option.
Figure 50. Configuring extra options
Step9
The files are being extracted in this step.
Figure 51. Installing
© Edunet Foundation. All rights reserved. | 169
Therefore, The Git installation is completed. Now you can access the Git
Gui and Git Bash.
The Git Gui looks like as
Figure 52. Git Gui
It facilitates with three features.
o Create New Repository
o Clone Existing Repository
o Open Existing Repository
The Git Bash looks like as
Figure 53. Git Bash
© Edunet Foundation. All rights reserved. | 170
3.1.3 What is GitHub?
GitHub is a Git repository hosting service. GitHub also facilitates with many of its
features, such as access control and collaboration. It provides a Web-based
graphical interface.
GitHub is an American company. It hosts source code of your project in the form of
different programming languages and keeps track of the various changes made by
programmers.
It offers both distributed version control and source code management
(SCM) functionality of Git. It also facilitates with some collaboration features such as
bug tracking, feature requests, task management for every project.
Figure 54. Github Features
Image Source: https://www.javatpoint.com/what-is-github
Features of GitHub
GitHub is a place where programmers and designers work together. They
collaborate, contribute, and fix bugs together. It hosts plenty of open source projects
and codes of various programming languages.
Some of its significant features are as follows.
Collaboration
Integrated issue and bug tracking
Graphical representation of branches
Git repositories hosting
Project management
Team management
Code hosting
Track and assign tasks
Conversations
Benefits of GitHub
GitHub can be separated as the Git and the Hub. GitHub service includes access
controls as well as collaboration features like task management, repository hosting,
and team management.
The key benefits of GitHub are as follows.
© Edunet Foundation. All rights reserved. | 171
It is easy to contribute to open source projects via GitHub.
It helps to create an excellent document.
You can attract recruiter by showing off your work. If you have a profile on
GitHub, you will have a higher chance of being recruited.
It allows your work to get out there in front of the public.
You can track changes in your code across versions.
3.1.3 Difference between git and GitHub
Figure 55. Git vs Github
Image source : https://visual.ly/community/Infographics/technology/what-
difference-between-git-and-github
3.1.4 Git
There are many words to define git, but it is an open-source distributed version
control system in simpler words.
Let us break each component in the definition and understand it.
o Open-source - A type of computer software released under a specific license.
The users are given permissions to use the code, modify the code, give
suggestions, clone the code to add new functionality. In other words, if the
software is open-source, it is developed collaboratively in a public manner.
The open-source softwares is cheaper, more flexible, and lasts longer than an
authority or a company. The products in the source code include code,
documents, formats for the users to understand and contribute to it. Using
open-source a project can be expanded to update or revise the current
features. Unix and Linux are examples of open-source softwares.
o Control system - The work of a control system is to track the content. In
other words, git is used to storing the content to provide the services and
features to the user.
© Edunet Foundation. All rights reserved. | 172
o Version Control system - Just like an app has different updates due to bugs
and additional feature addition, version changes, git also supports this feature.
Many developers can add their code in parallel. So the version control system
easily manages all the updates that are done previously.
Git provides the feature of branching in which the updated code can be done,
and then it can be merged with the main branch to make it available to the
users. It not only makes everything organized but keeps synchronization
among the developers to avoid any mishap. Other examples of version control
systems are Helix core, Microsoft TFS, etc.
o Distributed version control system - Here distributed version control
system means if a developer contributes to open source, the code will also be
available in his remote repository. The developer changes his local repository
and then creates a pull request to merge his changes in the central repository.
Hence, the word distributed means the code is stored in the central server
and stored in every developer's remote system.
Why is git needed?
When a team works on real-life projects, git helps ensure no code conflicts
between the developers. Furthermore, the project requirements change often. So
a git manages all the versions. If needed, we can also go back to the original
code. The concept of branching allows several projects to run in the same
codebase.
3.1.5 GitHub
By the name, we can visualize that it is a Hub, projects, communities,
etc. GitHub is a Git repository hosting service that provides a web-based
graphical interface. It is the largest community in the world. Whenever a project is
open-source, that particular repository gains exposure to the public and invites
several people to contribute.
The source code of several projects is available on github which developers can
use in any means.
Using github, many developers can work on a single project remotely because it
facilitates collaboration.
Features of gitHub
o Using github the project managers can collaborate, review and guide the
developers regarding any changes. This makes project management easy.
o The github repositories can be made public or private. Thus allowing safety to
an organization in case of a project.
o GitHub has a feature of pull requests and issues in which all the developers
can stay on the same page and organize.
o All the codes and their documentation are in one place in the same repository.
Hence it makes easy code hosting.
o There are some special tools that github uses to identify the vulnerabilities in
the code which other softwares do not have. Hence there is safety among the
developers from code start till launch.
o Github is available for mobile and desktops. The UI is so user-friendly that it
becomes straightforward to get comfortable with and use it.
© Edunet Foundation. All rights reserved. | 173
3.2 Getting Started with GitHub for Web Projects
3.2.1 Getting Started
1. Create a GitHub Account
Visit GitHub and sign up for a free account.
Follow the registration process and verify your email.
2. Install Git
Before you can use GitHub, you need to have Git installed on your local machine.
Windows: Download and install Git from git-scm.com.
macOS: Install Git using Homebrew: brew install git.
Linux: Use your package manager, for example, sudo apt-get install git on
Debian-based distributions.
3. Configure Git
After installing Git, configure it with your GitHub username and email:
git config --global user.name "Your GitHub Username"
git config --global user.email
[email protected]3.2.2 Creating and Managing a Repository
1. Create a New Repository on GitHub
Log in to your GitHub account.
Click the "+" icon in the upper-right corner and select "New repository".
Fill in the repository name, description, choose visibility (public or private), and
click "Create repository".
2. Clone the Repository
To work on your project locally, clone the repository to your computer:
git clone https://github.com/your-username/your-repository.git
This command copies the repository from GitHub to your local machine.
3. Add Files to Your Repository
Navigate to the cloned repository directory on your local machine.
Add your project files to this directory.
4. Track Changes with Git
Add: Stage your changes.
git add .
Commit: Save your changes in Git with a message.
git commit -m "Describe your changes here"
Push: Send your changes to the remote repository on GitHub.
git push -u origin main
© Edunet Foundation. All rights reserved. | 174
3.2.3 Working with Branches
Branches allow you to develop features, fix bugs, or experiment with new ideas
without affecting the main branch.
Create a Branch:
git checkout -b feature-branch
Switch to a Branch:
git checkout feature-branch
Merge a Branch: After making changes and committing them, merge the
branch into the main branch.
git checkout main
git merge feature-branch
Delete a Branch (if no longer needed):
git branch -d feature-branch
3.2.4 Collaborating with Pull Requests
Pull requests are essential for collaboration. They allow you to propose changes,
discuss them with your team, and review the code before merging.
Create a Pull Request:
1. Push your branch to GitHub.
2. Go to your repository on GitHub.
3. Click the "Pull Requests" tab, then "New Pull Request".
4. Select the branch you want to merge into the main branch and create
the pull request.
Review and Merge:
1. Review the changes in the pull request.
2. Discuss any modifications or improvements.
3. Merge the pull request once approved.
Managing Issues and Projects
GitHub also offers tools for tracking tasks and managing your project efficiently.
Issues: Use issues to track bugs, enhancements, or tasks. You can assign
issues to team members, label them, and organize them with milestones.
Projects: Create project boards to organize issues, pull requests, and notes
into a Kanban-style board for better visualization and management.
Best Practices
Frequent Commits: Commit changes regularly to keep track of progress and
reduce the risk of losing work.
Clear Commit Messages: Write descriptive commit messages to make it
easier to understand the history of changes.
© Edunet Foundation. All rights reserved. | 175
Branching Strategy: Use branches effectively to manage different aspects of
your project.
Code Reviews: Conduct thorough code reviews via pull requests to ensure
code quality and knowledge sharing.
3.3 AI-Assisted Coding
3.3.1 BlackBox AI
During this era of fantastical AI inventions, the world witnesses a great help
from machine learning-based applications and thus spending less time coding,
searching..etc
Nobody can deny that we should use these tools with caution and automate what
really needs to be automated rather than automating our whole life.
We already know Copilot, which is a great AI coding assistant. Still, the power of
programmers is their capability to discover and test a bunch of tools to prepare their
tools kit to work properly.
Blackbox AI is a cutting-edge artificial intelligence tool specifically designed to aid
developers like you. It acts as a virtual coding companion, capable of understanding
your requirements in plain English and translating them into functional code across
various programming languages. With Blackbox AI, you can bid farewell to the
frustrations of writing code from scratch or getting bogged down by syntax errors.
Let’s start the fun part.
Figure 56. BlackBox
Image Source: https://ismailouahbi.medium.com/blackbox-ai-powered-coding-assistant-
803df8633a9f
As seen in the above image, this tool will automate your coding process and helps
you answer coding questions as well as search for any code you want and use it
comfortably.
© Edunet Foundation. All rights reserved. | 176
There are a lot of plan to opt for in order to start coding with blackbox, We can opt for
the free plan
3.3.2 Step by Step Setup
To start this demo I’ll assume that you have your VSCode already installed, cause
we will be using VScode as a text editor.
Step 1: Open VSCode
1. Open Visual Studio Code (VSCode) on your computer.
Step 2: Access the Extensions View
1. Click on the Extensions icon in the Activity Bar on the side of the window. This
icon looks like four squares.
2. Alternatively, you can open the Extensions view by pressing Ctrl+Shift+X
(Windows/Linux) or Cmd+Shift+X (Mac).
Step 3: Search for Blackbox
1. In the Extensions view, type "Blackbox" in the search bar at the top.
Step 4: Install Blackbox Extension
1. Find the Blackbox extension in the list of search results.
2. Click the Install button next to the Blackbox extension.
Figure 57. VSCODE BLACKBOX EXTENSION
Step 7: Restart VSCode
1. It’s often a good idea to restart VSCode after installing new extensions to
ensure they are fully integrated.
3.3.3 Using Blackbox Features:
Blackbox offers various functionalities as you code:
AI-powered code completion: Blackbox AI helps you write code faster and
more efficiently by suggesting relevant code snippets and completions in real-
time as you type.
© Edunet Foundation. All rights reserved. | 177
Code chat: Stuck on a problem or need a fresh perspective? Blackbox AI's
code chat feature allows you to have a conversation with the AI about your
code. You can ask questions, describe functionalities, and get suggestions for
improvement or alternative approaches.
Figure 58. Deploying BlackBox AI
Documentation and debugging assistance: Blackbox AI can provide
relevant documentation and debugging suggestions alongside your code. This
can save you time searching for information and help you identify and fix bugs
more quickly.
3.4 Deploying static website Using GitHub Pages.
1. Create a GitHub Repository:
Head over to https://github.com/ and sign in to your account (or create a new
one if you don't have one).
Click on the "New repository" button.
Give your repository a name that follows “EdunetPortfolio” .
Provide a Description.
Optionally, add a brief description and initialize the repository with a README
file.
© Edunet Foundation. All rights reserved. | 178
Figure 59. Create a new repo in github
2. Prepare Your Website Files:
As mentioned before, ensure your website files (HTML, CSS, JavaScript, etc.)
are organized in a folder structure on your computer.
3. Drag and Drop to GitHub:
Login to your GitHub account and navigate to your newly created repository.
Locate the main code view section of your repository. It should display
existing files (if any) or be empty.
Drag all your website files and folders from your local directory and drop them
directly into the GitHub code view section.
© Edunet Foundation. All rights reserved. | 179
Figure 60. Import files
4. Commit the Changes (Optional):
GitHub might automatically detect the uploaded files and display a commit
message prompt.
You can add a descriptive commit message (e.g., "Initial website files") and
click "Commit changes" to create a snapshot of the uploaded files.
Figure 61. Imported files from local pc
5. GitHub Pages
Go to your GitHub repository settings.
Navigate to the "Pages" section.
© Edunet Foundation. All rights reserved. | 180
Figure 62. View all the files
6. Enable GitHub Pages and Configure Settings:
Go to your GitHub repository settings.
Navigate to the "Pages" section.
GitHub Pages might automatically detect your website files and offer a URL
based on your repository name. You can leave it as is or choose a custom
domain name (requires additional configuration).
Source: Select "Deploy from a branch" and choose the branch containing
your website files (usually main).
Select the main branch
Visibility: Set the desired visibility level (Public or Private).
Click "Save" to activate GitHub Pages for your repository.
© Edunet Foundation. All rights reserved. | 181
Figure 63. Git Hub Pages
Figure 64. Select Main Branch
7. Access Your Deployed Website:
After a short while (usually a few minutes), your website should be live!
The URL for your deployed website will be displayed in the GitHub Pages
section of your repository settings. It will likely follow the format
https://username.github.io (replace username with your GitHub username).
© Edunet Foundation. All rights reserved. | 182
Figure 65. Deploying your website
ImageSource: https://kaushaljoshi977.github.io/EdunetPortfolio/
© Edunet Foundation. All rights reserved. | 183
Chapter 4: ReactJS Essentials
Learning Outcomes:
Introduction to ReactJS
Setting up a React project with Create React App
Understanding components
Props and state (use State)
Handling forms and events
State management with Context API
Integrating API with React Application
4.1 Introduction to ReactJS
4.1.1 What is ReactJS?
ReactJS, sometimes referred to as a front-end JavaScript framework, is primarily used
for building UI components. Instead of directly manipulating the browser’s DOM, React
creates a virtual DOM in memory. It optimizes rendering performance by making
changes only where necessary.
It is known for its component-based architecture, allowing developers to create
reusable UI elements. React’s virtual DOM optimizes rendering performance.
4.1.2 History:
React was first used by Facebook in 2011 for their Newsfeed feature.
The initial public release (v0.3.0) happened in July 2013.
The current version of React is v18.0.0 (as of April 2022).
© Edunet Foundation. All rights reserved. | 184
4.1.3 Features of ReactJS:
Figure 66. Features of ReactJS
1. Component-Based Architecture:
React follows a component-based approach, allowing developers to create reusable
UI components.
Components can be nested, enabling the construction of complex applications from
simple building blocks.
2. Virtual DOM (Document Object Model):
React manages a virtual DOM, which optimizes rendering performance.
Changes are made to the virtual DOM, and only necessary updates are applied to the
actual DOM, resulting in smoother and faster performance.
3. Easy Creation of Dynamic Web Applications:
React simplifies dynamic web app development by reducing code complexity.
It supports building machine-readable code, enhancing functionality.
4. Reusable Components:
© Edunet Foundation. All rights reserved. | 185
React components are reusable and responsible for rendering small, reusable pieces
of HTML code.
Reusability is a core feature, making development efficient.
5. SEO Friendliness:
React applications can run on the server, improving search engine visibility.
The virtual DOM renders and returns content as regular web pages.
4.1.4 Advantages of ReactJS:
Figure 67. Advantages of ReactJS
Easy to Understand and Use:
Abundant documentation, tutorials, and training resources make ReactJS
accessible.
Especially beneficial for developers with a JavaScript background.
Performance Enhancement:
React’s virtual DOM ensures efficient updates, resulting in better performance.
Developers write to the virtual DOM, not directly to the browser’s DOM.
Reusable Components:
Reusable components simplify development and maintenance.
© Edunet Foundation. All rights reserved. | 186
Nested components allow complex app structures.
Support of Handy Tools:
ReactJS provides a useful set of tools, aiding developers in their tasks.
JavaScript Library:
ReactJS offers a rich JavaScript library, providing flexibility.
Testing Made Easy:
Native tools make testing ReactJS applications straightforward.
4.1.5 Disadvantages of ReactJS
Figure 68. Disadvantages of ReactJS
© Edunet Foundation. All rights reserved. | 187
High Pace of Development:
Frequent updates and changes can be challenging for developers to keep up with.
Continuous learning and skill updates are necessary.
Poor Documentation:
Rapid acceleration sometimes leads to inadequate documentation.
View Layer Only:
ReactJS focuses on UI layers, requiring additional technologies for other aspects of
development.
JSX Complexity:
JSX (JavaScript XML) coexists with React code but has a learning curve.
Some find it complex due to its HTML-like syntax.
4.2 Setting up a React project with Create React App
To run any React application, we must first set up a ReactJS development
environment.
We must have NodeJS installed on our PC. So, the very first step will be to install
NodeJS.
4.2.1 Installation of Node JS:
Step 1: Visit NodeJS Site:
You may visit https://nodejs.org/en/download/ of NodeJS to download and install the
latest version of NodeJS. Once we have set up NodeJS on our PC, the next thing
we need to do is set up React Boilerplate.
Step 2: Downloading the Node.js ‘.msi’ installer.
The first step to installing Node.js on Windows is to download the installer. Visit the
official Node.js website i.e.) https://nodejs.org/en/download/ and download the .msi
file according to your system environment (32-bit & 64-bit). An MSI installer will be
downloaded on your system.
© Edunet Foundation. All rights reserved. | 188
Figure 69. Download of Nodejs
Image Source: https://nodejs.org/en/download/prebuilt-installer
Step 3: Running the Node.js installer
Now you need to install the node.js installer on your PC. You need to follow the
following steps for the Node.js to be installed:-
Double-click on the .msi installer.
The Node.js Setup wizard will open.
Welcome To Node.js Setup Wizard.
Select “Next”
Figure 70. Nodejs Setup
After clicking “Next”, End-User License Agreement (EULA) will open.
Check “I accept the terms in the License Agreement”
Select “Next”
© Edunet Foundation. All rights reserved. | 189
Figure 71. Nodejs license Agreement
Destination Folder
Set the Destination Folder where you want to install Node.js & Select
“Next”
Figure 72. Choose destination Folder
Ready to Install Node.js.
The installer may prompt you to “install tools for native modules”.
Select “Install”
© Edunet Foundation. All rights reserved. | 190
Figure 73. Ready to install Nodejs
Installing Node.js.
Do not close or cancel the installer until the install is complete
Complete the Node.js Setup Wizard.
Click “Finish”
Figure 74. Nodejs Setup
Figure 75. Check Nodejs Version
If node.js was completely installed on your system, the command prompt will print
the version of the node.js installed.
© Edunet Foundation. All rights reserved. | 191
4.3 Understanding Components
4.3.1 Components
A Component is considered as the core building blocks of a React application. It
makes the task of building UIs much easier. Each component exists in the same space,
but they work independently from one another and merge all in a parent component,
which will be the final UI of your application.
In ReactJS, we have mainly two types of components. They are
Functional Components
Class Components
Let’s delve into React function components and class components,
4.3.1.1 React Function Component:
Function components are simple JavaScript functions that take props (short for
properties) as input and return JSX (JavaScript XML) elements. They are often used
for presentational or stateless components. Here’s how you define a function
component:
Example-1: Simple Functional Component
Code:
import React, { Component } from 'react';
function App() {
const text = 'EDUNET FOUNDATION';
return (
<div className="App">
<p> {text}</p>
</div>
);
}
export default App;
Output:
© Edunet Foundation. All rights reserved. | 192
Example-2: Components in Components
Code:
import React from 'react';
const ParentComponent = () => {
// Inner function to handle some logic
const handleClick = () => {
alert('Button clicked!');
};
return (
<div>
<h1>Child component click on the button</h1>
<ChildComponent handleClick={handleClick} />
</div>
);
};
const ChildComponent = ({ handleClick }) => {
return (
<div>
<button onClick={handleClick}>Click Me!</button>
</div>
);
};
export default ParentComponent;
Output:
Explanation:
ParentComponent: This is the main function component. Inside it, there is a
function handleClick defined. This function will be called when a button in the
ChildComponent is clicked.
handleClick: This is the inner function that shows an alert when called. It is
defined inside the ParentComponent to keep the click handling logic
encapsulated within the parent.
© Edunet Foundation. All rights reserved. | 193
ChildComponent: This is a child function component that receives handleClick
as a prop. It renders a button, and when the button is clicked, it calls the
handleClick function passed down from the parent.
Props: The handleClick function is passed to the ChildComponent as a prop.
This way, the child can trigger actions or logic defined in the parent component.
Usage
To use the above component, you can import and render the ParentComponent
in your main application file (e.g., App.js):
import React from 'react';
import ParentComponent from './ParentComponent'; // Adjust the path as
necessary
const App = () => {
return (
<div>
<ParentComponent />
</div>
);
};
This setup allows for clear organization of your code, making it easier to manage and
understand. Inner functions help in keeping the components clean and modular.
Key points about function components:
They are lightweight and concise.
They accept props as input.
They don’t manage a state or have lifecycle methods (until React Hooks came
along).
4.3.1.2 React Class Component:
Class components are ES6 classes that extend either React.Component or
React.PureComponent. They have a render() method where you define the structure
of your component’s UI using JSX. Class components are used for components that
need to manage a state or have lifecycle methods. Here’s an example:
Example-1: Simple example of a React class component that displays a
message
Code:
import React, { Component } from 'react';
class Greeting extends Component {
render() {
© Edunet Foundation. All rights reserved. | 194
return (
<div>
<h1>Hello, World!</h1>
</div>
);
}
}
export default Greeting;
Output:
Explanation:
1. Importing React and Component: The React and Component classes are
imported from the react package.
import React, { Component } from 'react';
2. Class Definition: The Greeting class extends React.Component, making it a React
component.
class Greeting extends Component {
3. render Method: This method returns the JSX to render the component. It outputs
a div containing an h1 element with the text "Hello, World!".
render() {
return (
<div>
<h1>Hello, World!</h1>
</div>
);
}
Usage:
To use the Greeting class component, you can import and render it in your main
application file (e.g., App.js):
import React from 'react';
import Greeting from './Greeting'; // Adjust the path as necessary
const App = () => {
return (
© Edunet Foundation. All rights reserved. | 195
<div>
<Greeting />
</div>
);
};
export default App;
Explanation of Usage
Importing Greeting Component: The Greeting component is imported from
its file.
import Greeting from './Greeting';
Rendering Greeting Component: The Greeting component is rendered inside
the App component.
const App = () => {
return (
<div>
<Greeting />
</div>
);
};
Exporting App Component: The App component is exported as the default
export.
export default App;
This setup will render a simple "Hello, World!" message on the screen when you run
your React application. This example demonstrates the basic structure of a React
class component, including importing dependencies, defining the class, and using the
render method to return JSX.
Example-2: Components in Components
Code:
import React, { Component } from 'react';
class App extends React.Component {
render() {
return (
<div>
<First/>
<Second/>
</div>
);
}
}
class First extends React.Component {
render() {
© Edunet Foundation. All rights reserved. | 196
return (
<div>
<h1>EDUNET FOUNDATION</h1>
</div>
);
}
}
class Second extends React.Component {
render() {
return (
<div>
<h1>Edunet Foundation</h1>
<h2>https://edunetfoundation.org/</h2>
<p>EMPOWERED. EQUIPPED. FUTURE-READY
Get skilled, Get certified- Learn the best, from the best!</p>
</div>
);
}
}
export default App;
Output:
Example-3: React class component that uses a constructor to initialize its state
and render a message
Code:
import React, { Component } from 'react';
class Welcome extends Component {
constructor(props) {
© Edunet Foundation. All rights reserved. | 197
super(props);
// Initialize state
this.state = {
name: 'Edunet Foundation',
};
}
render() {
return (
<div>
<h1>Hello, {this.state.name}!</h1>
</div>
);
}
}
export default Welcome;
Output:
Explanation:
Constructor: The constructor is used to initialize the state.
constructor(props) {
super(props);
// Initialize state
this.state = {
name: 'World',
};
}
super(props): Calls the constructor of the parent class (Component) with
props.
this.state: Initializes the component's state with a name property set to 'World'.
© Edunet Foundation. All rights reserved. | 198
Key points about class components:
They allow managing state using this. state.
They can have lifecycle methods like componentDidMount,
componentDidUpdate, etc.
React Hooks have blurred the distinction between function and class
components, but both are still widely used.
4.3.1.3 When to Use Which?
Function Components:
Use them for simple UI rendering.
When you don’t need state or lifecycle methods.
Ideal for presentational components.
Class Components:
Use them when you need state management or lifecycle methods.
For more complex logic and interactions.
© Edunet Foundation. All rights reserved. | 199
4.4 Prop & States
Let’s dive into the concepts of props and state in React, along with a code example to
illustrate their usage.
4.4.1 Props (Properties):
Props (short for “properties”) allow you to pass data from a parent component
to its child components. They serve as a way to communicate information
between different parts of your application.
Props are read-only, meaning that once you pass them to a component, their
values cannot be modified within that component.
You can use props with both functional components and class components.
Common use cases for props include passing configuration values, such as
text content, styles, or callback functions.
Key points about Props:
Purpose: Props allow you to pass data or properties from a parent component
to its child components.
Ownership: Props are owned by the parent component and are read-only
within the child component.
Usage: They are used for communication between components.
Mutability: Props are immutable (cannot be modified).
Example-1: Passing a Value as a Prop:
In this example, we have a parent component that passes a value as a
prop to a child component. The child component then displays the value
as text on the screen.
Code:
import React from 'react';
import PropTypes from 'prop-types';
// Parent component
function App() {
return (
<Note id="1" title="This is the title" content="Blog about
props" />
);
}
// Child component
function Note(props) {
return (
<div>
<h1>{props.title}</h1>
<p>{props.content}</p>
</div>
© Edunet Foundation. All rights reserved. | 200
);
}
export default App;
Output:
© Edunet Foundation. All rights reserved. | 201
Example-2: Passing a Function as a Prop:
In this example, the parent component passes a function as a prop to the
child component. The child component calls the function when a button
is clicked.
Code:
import React from 'react';
import PropTypes from 'prop-types';
// Parent component
function App() {
const printNote = (content) => {
console.log(content);
};
return (
<Note
id="1"
title="This is the title"
content="Blog about props"
onClickNote={printNote}
/>
);
}
// Child component
function Note(props) {
return (
<div>
<h1>{props.title}</h1>
<p>{props.content}</p>
<button onClick={() => props.onClickNote(props.content)}>
Print Note
</button>
</div>
);
}
export default App;
© Edunet Foundation. All rights reserved. | 202
Output:
© Edunet Foundation. All rights reserved. | 203
Example-3: Passing an Object as a Prop:
In this example, the parent component passes an object as a prop to the
child component. The child component uses the object to display
information on the screen.
Code:
import React from 'react';
import PropTypes from 'prop-types';
// Parent component
function App() {
const user = {
name: "uma",
email: "
[email protected]",
};
return <Note user={user} />;
}
// Child component
function Note(props) {
return (
<div>
<p>Name: {props.user.name}</p>
<p>Email: {props.user.email}</p>
</div>
);
}
export default App;
Output:
© Edunet Foundation. All rights reserved. | 204
4.4.2 State:
The state represents a component’s internal data. It’s used to manage dynamic
information that can change over time.
Unlike props, the state is mutable within the component where it’s defined.
You can think of the state as a local data storage that’s specific to a particular
component.
The state allows components to be interactive and update their content
dynamically.
To modify the state, you use this.setState() method, which triggers a re-render
of the component.
Key points about State:
Purpose: State represents real-time data specific to a component. It’s used for
managing dynamic information that can change over time.
Ownership: State is owned by the component itself and can be modified within
that component.
Usage: Used for managing internal component data.
Mutability: State is mutable (can be modified using this.setState()).
Example-1: Creating a Stateful Component
Let's create a simple counter component to understand how state works.
Code:
import React, { useState } from 'react';
function Counter() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
export default Counter;
© Edunet Foundation. All rights reserved. | 205
Output:
Explanation of the Example Code:
Importing useState Hook:
import React, { useState } from 'react';
We import useState from React to use state within a functional component.
Declaring State Variable:
const [count, setCount] = useState(0);
We declare a state variable count and a function setCount to update the state.
useState(0) initializes count with the value 0.
Rendering State:
<p>You clicked {count} times</p>
We display the current state value in a paragraph.
Updating State:
<button onClick={() => setCount(count + 1)}>
Click me
</button>
We add a button that increments the count state variable by 1 each time it is clicked.
The onClick event handler calls the setCount function to update the state.
© Edunet Foundation. All rights reserved. | 206
Example-2: Using State-in-Class Components
While functional components and hooks (like useState) are recommended in
modern React development, it's useful to see how state was traditionally
managed in class components.
Code:
import React, { Component } from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
handleClick = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={this.handleClick}>
Click me
</button>
</div>
);
}
}
export default Counter;
© Edunet Foundation. All rights reserved. | 207
Output:
Explanation of the Class Component Example
Initializing State in Constructor:
constructor(props) {
super(props);
this.state = { count: 0 };
}
The state is initialized in the constructor method.
Updating State with setState:
handleClick = () => {
this.setState({ count: this.state.count + 1 });
};
The handleClick method updates the state using this.setState.
Rendering State:
<p>You clicked {this.state.count} times</p>
We display the current state value.
Event Handler for Button Click:
© Edunet Foundation. All rights reserved. | 208
<button onClick={this.handleClick}>
Click me
</button>
The button uses the handleClick method as an event handler to update the state.
Conclusion of State:
Using state in React allows you to create interactive and dynamic components. The
useState hook is the modern approach to managing state in functional components,
while class components use this.state and this.setState. Both methods enable
components to maintain and update their own state, leading to re-rendering of the
component when the state changes.
4.4.3 Application of Props & State:
Props and state are fundamental concepts in React, and they are used in a wide
variety of applications to manage data flow and user interactions. Here are some
common applications that utilize props and state.
1. Form Handling:
Forms often use the state to manage user input and props to pass data and handlers
between components.
State: To manage the input values.
Props: To pass the form data and submit handlers to other components.
2. Todo List:
A to-do list application uses a state to keep track of the list of tasks and props to pass
down the task data and handlers to the task components.
State: To manage the list of tasks and their completion status.
Props: To pass task data and handlers to child components.
3. Counter:
A simple counter application uses state to manage the counter value and props to
pass the value and handlers to the counter display component.
State: To manage the counter value.
Props: To pass the counter value and increment/decrement handlers to child
components.
4. Profile Viewer:
A profile viewer application uses the state to manage the profile data and props to
pass the profile details to child components for display.
State: To manage the profile data.
Props: To pass the profile data to child components for display.
© Edunet Foundation. All rights reserved. | 209
Example: Shopping Cart Application
A shopping cart application uses state to manage the list of items in the cart and props
to pass item data and handlers to add or remove items from the cart.
State: To manage the items in the cart and their quantities.
Props: To pass item data and handlers to the cart item components.
Code:
import React, { Component } from 'react';
class CartItem extends Component {
render() {
const { item, onRemove } = this.props;
return (
<div>
<span>{item.name} - ${item.price} x {item.quantity}</span>
<button onClick={() => onRemove(item.id)}>Remove</button>
</div>
);
}
}
class ShoppingCart extends Component {
constructor(props) {
super(props);
this.state = {
items: [
{ id: 1, name: 'Item 1', price: 10, quantity: 1 },
{ id: 2, name: 'Item 2', price: 20, quantity: 2 },
],
};
}
handleRemoveItem = (id) => {
this.setState((prevState) => ({
items: prevState.items.filter((item) => item.id !== id),
}));
};
render() {
const total = this.state.items.reduce(
(sum, item) => sum + item.price * item.quantity,
0
);
© Edunet Foundation. All rights reserved. | 210
return (
<div>
<h1>Shopping Cart</h1>
<div>
{this.state.items.map((item) => (
<CartItem key={item.id} item={item}
onRemove={this.handleRemoveItem} />
))}
</div>
<h2>Total: ${total}</h2>
</div>
);
}
}
export default ShoppingCart;
Output:
4.4.4 When to Use Which?
Use Props:
When you need to pass data from a parent to a child component.
When the data is immutable and should not change within the child
component.
For configuring child components with data or behavior.
To pass callback functions for event handling.
Use State:
When you need to manage data that changes over time.
When the data is specific to a component and does not need to be shared.
For handling user inputs and form data.
For managing dynamic UI elements and interactions.
© Edunet Foundation. All rights reserved. | 211
4.5 Handling forms and events
Handling forms and events in ReactJS is essential for creating interactive web
applications. React makes this process straightforward by providing mechanisms to
manage state and handle events in a declarative way. Here's a step-by-step guide to
handling forms and events in ReactJS.
Creating a Form Component
Let's create a simple form component with input fields for a user's name and email.
Code: Form Component (Form.js)
import React, { useState } from 'react';
function Form() {
// Define state for form fields
const [name, setName] = useState('');
const [email, setEmail] = useState('');
// Handle input change
const handleInputChange = (event) => {
const { name, value } = event.target;
if (name === 'name') {
setName(value);
} else if (name === 'email') {
setEmail(value);
}
};
// Handle form submission
const handleSubmit = (event) => {
event.preventDefault();
alert(`Name: ${name}, Email: ${email}`);
// Reset form fields
setName('');
setEmail('');
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>
Name:
<input
type="text"
name="name"
© Edunet Foundation. All rights reserved. | 212
value={name}
onChange={handleInputChange}
/>
</label>
</div>
<div>
<label>
Email:
<input
type="email"
name="email"
value={email}
onChange={handleInputChange}
/>
</label>
</div>
<button type="submit">Submit</button>
</form>
);
}
export default Form;
Code:Using Form Component
To use the Form component, import it and include it in your main application
component (e.g., App.js).
import React from 'react';
import Form from './Form';
function App() {
return (
<div>
<h1>React Form Handling</h1>
<Form />
</div>
);
}
export default App;
Output:
© Edunet Foundation. All rights reserved. | 213
Explanation of the Form Component:
State Management:
const [name, setName] = useState('');
const [email, setEmail] = useState('');
We use the useState hook to create state variables for name and email.
Handling Input Change:
const handleInputChange = (event) => {
const { name, value } = event.target;
if (name === 'name') {
setName(value);
} else if (name === 'email') {
setEmail(value);
}
};
Handling Form Submission:
const handleSubmit = (event) => {
event.preventDefault();
alert(`Name: ${name}, Email: ${email}`);
setName('');
setEmail('');
};
© Edunet Foundation. All rights reserved. | 214
This function prevents the default form submission behavior, displays an alert with the
form data, and resets the form fields.
Form JSX Structure:
<form onSubmit={handleSubmit}>
<div>
<label>
Name:
<input type="text" name="name" value={name}
onChange={handleInputChange} />
</label>
</div>
<div>
<label>
Email:
<input type="email" name="email" value={email}
onChange={handleInputChange} />
</label>
</div>
<button type="submit">Submit</button>
</form>
The form contains input fields for the name and email, each with an onChange event
handler to update the state and a onSubmit event handler to handle form submission.
Explanation of the Main Application:
Import the Form Component:
import Form from './Form';
Import the Form component to use it in the main application component.
Include the Form Component:
<Form />
Add the Form component within the App component's render method.
© Edunet Foundation. All rights reserved. | 215
Hands-on: Building Simple React Application – Advise Generator Application
Code:
src/Components/AdviceList.js:
import React, { useState } from 'react';
import adviceData from './adviceData';
const AdviceList = ({ onSelectAdvice }) => {
const [category, setCategory] = useState('');
const getRandomAdvice = (category) => {
const advices = adviceData[category];
const randomIndex = Math.floor(Math.random() * advices.length);
return advices[randomIndex];
};
const handleGenerateAdvice = () => {
if (category) {
const advice = getRandomAdvice(category);
onSelectAdvice(advice);
}
};
return (
<div>
<select value={category} onChange={(e) =>
setCategory(e.target.value)}>
<option value="">Select a category</option>
<option value="financial">Financial</option>
<option value="health">Health</option>
<option value="education">Education</option>
</select>
<button onClick={handleGenerateAdvice} disabled={!category}>
Get Advice
</button>
</div>
);
};
export default AdviceList;
© Edunet Foundation. All rights reserved. | 216
src/Components/adviceData.js
const adviceData = {
financial: [
"Save a portion of your income regularly.",
"Create a budget and stick to it.",
"Invest in your future.",
"Avoid unnecessary debt.",
"Build an emergency fund.",
"Track your spending.",
"Plan for retirement early.",
"Diversify your investments."
],
health: [
"Eat a balanced diet.",
"Exercise regularly.",
"Get enough sleep.",
"Stay hydrated.",
"Avoid smoking and excessive alcohol.",
"Manage stress effectively.",
"Maintain a healthy weight.",
"Regularly check-up with your doctor."
],
education: [
"Never stop learning.",
"Read regularly.",
"Seek out mentors.",
"Practice critical thinking.",
"Stay curious and ask questions.",
"Manage your time effectively.",
"Set learning goals.",
"Take breaks to avoid burnout."
]
};
export default adviceData;
src/App.js:
import React, { useState } from 'react';
import './App.css';
import AdviceList from './Components/AdviceList';
function App() {
const [advice, setAdvice] = useState('');
return (
<div className="App">
© Edunet Foundation. All rights reserved. | 217
<header className="App-header">
<h1>Advice Generator</h1>
<AdviceList onSelectAdvice={setAdvice} />
{advice && <p>{advice}</p>}
</header>
</div>
);
}
export default App;
src/index.js:
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
public/index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>Advice Generator</title>
© Edunet Foundation. All rights reserved. | 218
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
OUTPUT:
Conclusion of handling forms and Events:
Handling forms and events in React involves managing state and event handlers. The
useState hook is essential for managing form field values, and event handlers
(onChange, onSubmit) are used to update the state and handle form submissions.
This example demonstrates a simple form with input fields for a user's name and email,
showcasing how to handle user input and form submission in a React application.
© Edunet Foundation. All rights reserved. | 219
4.6 State Management with Context API
Managing state in larger React applications can be challenging, especially when
dealing with deeply nested components. The Context API is a powerful tool in React
that helps manage the global state across the application without prop drilling.
Here’s a step-by-step guide to using the Context API for state management
Creating a Context
Create a Context File: Create a new file, UserContext.js, in the src directory
import React, { createContext, useState } from 'react';
// Create the context
export const UserContext = createContext();
// Create a provider component
export const UserProvider = ({ children }) => {
const [user, setUser] = useState({ name: 'John Doe', email:
'
[email protected]' });
return (
<UserContext.Provider value={{ user, setUser }}>
{children}
</UserContext.Provider>
);
};
Using the Context in Your Application
Wrap Your Application with the Provider: Modify App.js to use the UserProvider.
import React from 'react';
import { UserProvider } from './UserContext';
import UserProfile from './UserProfile';
import UserSettings from './UserSettings';
function App() {
return (
<UserProvider>
<div className="App">
<h1>React Context API Example</h1>
<UserProfile />
<UserSettings />
© Edunet Foundation. All rights reserved. | 220
</div>
</UserProvider>
);
}
export default App;
Consuming Context in Components
Create Components to Consume the Context: Create UserProfile.js and
UserSettings.js to consume the context.
import React, { useContext } from 'react';
import { UserContext } from './UserContext';
function UserProfile() {
const { user } = useContext(UserContext);
return (
<div>
<h2>User Profile</h2>
<p>Name: {user.name}</p>
<p>Email: {user.email}</p>
</div>
);
}
export default UserProfile;
import React, { useContext, useState } from 'react';
import { UserContext } from './UserContext';
function UserSettings() {
const { user, setUser } = useContext(UserContext);
const [newName, setNewName] = useState(user.name);
const [newEmail, setNewEmail] = useState(user.email);
const handleUpdate = () => {
setUser({ name: newName, email: newEmail });
};
return (
<div>
<h2>User Settings</h2>
<label>
Name:
<input
type="text"
© Edunet Foundation. All rights reserved. | 221
value={newName}
onChange={(e) => setNewName(e.target.value)}
/>
</label>
<label>
Email:
<input
type="email"
value={newEmail}
onChange={(e) => setNewEmail(e.target.value)}
/>
</label>
<button onClick={handleUpdate}>Update</button>
</div>
);
}
export default UserSettings;
Output:
Explanation:
Creating Context:
import React, { createContext, useState } from 'react';
// Create the context
export const UserContext = createContext();
// Create a provider component
export const UserProvider = ({ children }) => {
const [user, setUser] = useState({ name: 'John Doe', email:
'
[email protected]' });
© Edunet Foundation. All rights reserved. | 222
return (
<UserContext.Provider value={{ user, setUser }}>
{children}
</UserContext.Provider>
);
};
Here, we create a context and a provider component that holds the user state. The
provider makes the state available to any child components that consume the context.
Using Context Provider:
import React from 'react';
import { UserProvider } from './UserContext';
import UserProfile from './UserProfile';
import UserSettings from './UserSettings';
function App() {
return (
<UserProvider>
<div className="App">
<h1>React Context API Example</h1>
<UserProfile />
<UserSettings />
</div>
</UserProvider>
);
}
export default App;
Here, we wrap our entire application with the UserProvider, allowing all child
components to access the user state.
Consuming Context:
import React, { useContext } from 'react';
import { UserContext } from './UserContext';
function UserProfile() {
const { user } = useContext(UserContext);
return (
<div>
<h2>User Profile</h2>
<p>Name: {user.name}</p>
<p>Email: {user.email}</p>
</div>
© Edunet Foundation. All rights reserved. | 223
);
}
export default UserProfile;
import React, { useContext, useState } from 'react';
import { UserContext } from './UserContext';
function UserSettings() {
const { user, setUser } = useContext(UserContext);
const [newName, setNewName] = useState(user.name);
const [newEmail, setNewEmail] = useState(user.email);
const handleUpdate = () => {
setUser({ name: newName, email: newEmail });
};
return (
<div>
<h2>User Settings</h2>
<label>
Name:
<input
type="text"
value={newName}
onChange={(e) => setNewName(e.target.value)}
/>
</label>
<label>
Email:
<input
type="email"
value={newEmail}
onChange={(e) => setNewEmail(e.target.value)}
/>
</label>
<button onClick={handleUpdate}>Update</button>
</div>
);
}
export default UserSettings;
In UserProfile.js and UserSettings.js, we use the useContext hook to access the user
state and the setUser function from the context. UserProfile displays the current user
information, while UserSettings allows updating the user information.
© Edunet Foundation. All rights reserved. | 224
Conclusion of State Management with context API:
The Context API in React provides a way to share state across the entire application
or parts without manually passing props at every level. By using the Context API, you
can manage the global state efficiently and make your application more maintainable
and scalable.
© Edunet Foundation. All rights reserved. | 225
4.7 Integrating API with React Application
Integrating an API with a React application is a common task that involves fetching
data from a backend service and displaying it in your React components.
Here's a step-by-step guide on integrating an API with a React application.
Creating a Component to Fetch Data
Create a Component: Create a new component, UserList.js, in the src directory.
Code:
import React, { useState, useEffect } from 'react';
function UserList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
// Fetch data from API
fetch('https://jsonplaceholder.typicode.com/users')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
setUsers(data);
setLoading(false);
})
.catch(error => {
setError(error);
setLoading(false);
});
}, []);
if (loading) {
return <p>Loading...</p>;
}
if (error) {
return <p>Error: {error.message}</p>;
}
© Edunet Foundation. All rights reserved. | 226
return (
<div>
<h1>User List</h1>
<ul>
{users.map(user => (
<li key={user.id}>{user.name} - {user.email}</li>
))}
</ul>
</div>
);
}
export default UserList;
Using the Component in Your Application
Include the Component in App.js: Modify App.js to include the UserList component.
import React from 'react';
import UserList from './UserList';
function App() {
return (
<div className="App">
<h1>API Integration Example</h1>
<UserList />
</div>
);
}
export default App;
© Edunet Foundation. All rights reserved. | 227
Output:
Explanation:
State Management:
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
We use the useState hook to manage the state for users, loading, and error.
Fetching Data with useEffect:
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
© Edunet Foundation. All rights reserved. | 228
setUsers(data);
setLoading(false);
})
.catch(error => {
setError(error);
setLoading(false);
});
}, []);
The useEffect hook is used to fetch data when the component mounts. We fetch data
from the API, handle the response, and update the state. If there's an error, we catch
it and update the error state.
Handling Loading and Error States:
if (loading) {
return <p>Loading...</p>;
}
if (error) {
return <p>Error: {error.message}</p>;
}
We display a loading message while fetching data and an error message if there's an
error.
Displaying Data:
return (
<div>
<h1>User List</h1>
<ul>
{users.map(user => (
<li key={user.id}>{user.name} - {user.email}</li>
))}
</ul>
</div>
);
We map over the users array and display each user's name and email in a list.
Enhancing with Async/Await:
You can also use async/await for cleaner asynchronous code. Here’s how you can
modify the data fetching function using async/await.
Hands-on: Integrate an AI-related JSON file with a React application.
Code:
© Edunet Foundation. All rights reserved. | 229
Public/aiData.json:
[
{
"id": 1,
"name": "Image Classification",
"description": "Classify images into predefined categories using deep
learning models."
},
{
"id": 2,
"name": "Natural Language Processing",
"description": "Analyze and understand human language through machine
learning."
},
{
"id": 3,
"name": "Recommendation System",
"description": "Predict user preferences and recommend items based on
past behavior."
}
]
Src/Components/AiProjects.js:
import React, { useEffect, useState } from 'react';
const AiProjects = () => {
const [projects, setProjects] = useState([]);
useEffect(() => {
fetch('/aiData.json')
.then(response => response.json())
.then(data => setProjects(data))
.catch(error => console.error('Error fetching the data:', error));
}, []);
return (
<div>
<h1>AI Projects</h1>
<ul>
{projects.map(project => (
<li key={project.id}>
<h2>{project.name}</h2>
<p>{project.description}</p>
</li>
))}
</ul>
© Edunet Foundation. All rights reserved. | 230
</div>
);
};
export default AiProjects;
src/App.js:
import React from 'react';
import AiProjects from './components/AiProjects';
function App() {
return (
<div className="App">
<AiProjects />
</div>
);
}
export default App;
src/index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
Output:
© Edunet Foundation. All rights reserved. | 231
Conclusion of Integrating API with React Application:
Integrating an API with a React application involves fetching data, handling loading
and error states, and displaying the data. By using the useState and useEffect hooks,
you can manage the state and lifecycle of your components effectively.
© Edunet Foundation. All rights reserved. | 232
Chapter 5: ReactJS Advance Guide
Learning Outcomes:
Explore Hooks (useEffect, custom hooks, useRef, useReducer,
useMemo, use callback).
Page Routing.
Optimizing performance.
Code splitting and lazy loading.
Setting up Redux with React.
Understand Actions, reducers, and the store.
Using Redux Dev Tools.
5.1 Explore Hooks
React Hooks, introduced in React 16.8, allows you to use state and other React
features without writing a class. They provide a more direct API to the React concepts
you are familiar with, such as state, lifecycle, and context.
Key Features of React Hooks:
useState: Adds state to functional components.
useEffect: Manages side effects like data fetching and subscriptions.
useContext: Accesses context values without nesting.
useReducer: Manages complex state logic with reducers.
useMemo: Memorizes values to optimize performance.
useCallback: Memorizes callbacks to optimize performance.
useRef: Accesses and interacts with DOM elements directly.
Advantages of React Hooks:
Figure 76. Advantages of React Hooks
© Edunet Foundation. All rights reserved. | 233
Simplicity: Hooks make it easier to understand and write components by
removing the need for classes.
Code Reusability: Custom hooks allow you to extract and reuse stateful logic
across multiple components.
Separation of Concerns: Hooks enable better separation of concerns by
allowing you to split related logic into different functions.
Easier to Test: Functions and hooks are generally easier to test compared to
class components.
Improved Performance: Hooks like useMemo and useCallback help optimize
performance by memoizing values and functions.
Disadvantages of React Hooks:
Figure 77. Disadvantages of React Hooks
Learning Curve: Hooks introduce a new way of thinking about state and
lifecycle, which can be challenging for those accustomed to class components.
Complexity in Large Components: Overusing hooks in large components
can lead to complexity and make the code harder to follow.
Performance Pitfalls: Incorrect use of hooks like useEffect can lead to
performance issues or unintended side effects.
History of React Hooks:
February 2019: React 16.8 was released, introducing hooks as a new feature.
Prior to Hooks: React primarily relied on class components for state
management and lifecycle methods.
Development Motivation: Hooks were developed to address limitations in
class components, such as complex patterns for reusing stateful logic and the
challenge of understanding large class components.
5.1.1 Understanding useEffect in React
The useEffect hook lets you perform side effects in function components. It is the
functional component equivalent of lifecycle methods in class components such as
componentDidMount, componentDidUpdate, and componentWillUnmount.
Example:
Here's a basic example demonstrating how to use useEffect to perform a side
effect, such as fetching data when the component mounts.
© Edunet Foundation. All rights reserved. | 234
Code:
import React, { useState, useEffect } from 'react';
function DataFetcher() {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Fetch data from an API
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(data => {
setData(data); // Update state with fetched data
setLoading(false); // Set loading to false once data is fetched
})
.catch(error => console.error('Error fetching data:', error));
}, []); // Empty dependency array ensures this runs only once after the initial
render
if (loading) {
return <p>Loading...</p>;
}
return (
<div>
<h1>Fetched Data</h1>
<ul>
{data.map(item => (
<li key={item.id}>{item.title}</li>
))}
</ul>
</div>
);
}
export default DataFetcher;
© Edunet Foundation. All rights reserved. | 235
Output:
Explanation:
State Initialization:
const [data, setData] = useState([]); initializes the state to hold the fetched data.
const [loading, setLoading] = useState(true); initializes the state to track the loading status.
useEffect Hook:
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(data => {
setData(data);
setLoading(false);
})
.catch(error => console.error('Error fetching data:', error));
© Edunet Foundation. All rights reserved. | 236
}, []);
The useEffect hook takes a function and a dependency array as arguments.
The function contains the side effect, in this case, fetching data from an API.
The empty dependency array [] means this effect will run only once after the
initial render, mimicking the behavior of componentDidMount.
Fetching Data:
fetch('https://jsonplaceholder.typicode.com/posts') initiates a network request.
.then(response => response.json()) parses the response to JSON.
.then(data => { setData(data); setLoading(false); }) updates the data state with
the fetched data and sets loading to false.
Error Handling:
.catch(error => console.error('Error fetching data:', error)); logs any errors that occur
during the fetch operation.
Conditional Rendering:
if (loading) { return <p>Loading...</p>; } displays a loading message while the data is
being fetched.
Once the data is fetched, it is displayed in a list format.
Cleanup in useEffect
For side effects that require cleanup, such as subscriptions or timers, useEffect can
return a cleanup function. This function will be called when the component unmounts
or before the effect runs again.
Example with Cleanup:
import React, { useState, useEffect } from 'react';
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setCount(prevCount => prevCount + 1);
}, 1000);
// Cleanup function to clear the interval
return () => clearInterval(interval);
}, []); // Empty dependency array to mimic componentDidMount and
componentWillUnmount
return (
<div>
<p>Count: {count}</p>
</div>
);
© Edunet Foundation. All rights reserved. | 237
}
export default Timer;
Explanation of Cleanup:
Setting up the Interval:
const interval = setInterval(() => { setCount(prevCount => prevCount + 1); }, 1000);
sets up an interval that increments the count every second.
Cleanup Function:
return () => clearInterval(interval); returns a cleanup function that clears the interval
when the component unmounts or before the effect runs again, preventing memory
leaks.
When to Use useEffect:
Fetching Data:
Scenario: You need to fetch data from an API when a component mounts or when
specific state or prop values change.
Example: Fetching a list of users when a component loads.
Subscribing to Services:
Scenario: You need to subscribe to a service or set up a connection (e.g., WebSocket,
external event listeners) when a component mounts, and clean up the subscription
when the component unmounts.
Example: Subscribing to a WebSocket for real-time updates.
Updating the DOM:
Scenario: You need to manually interact with the DOM after React has rendered it.
Example: Updating the document title or focusing an input element.
Setting up Timers:
Scenario: You need to set up timers or intervals and clear them when the component
unmounts.
Example: Updating a counter every second.
Handling Side Effects Based on State or Props Changes:
Scenario: You need to perform side effects in response to changes in state or props.
Example: Logging the user activity whenever a specific prop changes.
Cleaning Up Resources:
Scenario: You need to clean up resources to avoid memory leaks, such as removing
event listeners or cancelling subscriptions.
© Edunet Foundation. All rights reserved. | 238
Example: Removing a resize event listener.
Conclusion of useEffect Hooks:
The useEffect hook is a powerful tool for handling side effects in React functional
components. It can replace lifecycle methods, allowing for more concise and readable
code. Understanding how to use useEffect effectively, including how to handle
cleanup, is essential for managing component behavior and state in modern React
applications.
5.1.2 Custom Hook in React
Custom hooks are a powerful way to reuse stateful logic across multiple components
in React. They allow you to extract and share logic while keeping your components
clean and focused on rendering.
Example:
Custom Hook: useFetch
Suppose we have to use this counter in multiple components then we would
require a custom hook that can perfrom the same function multiple times.
Code:
useCustomHook.js:
import {useState , useEffect} from "react";
function useCustomHook(initializer , componentName){
const [counter , setCounter] = useState(initializer);
// Increases the value of counter by 1
function resetCounter(){
setCounter(counter + 1);
}
useEffect(() => {
// Some logic that will be used in multiple components
console.log("The button of the "
+ componentName + " is clicked "
+ counter + " times.");
} , [counter , componentName]);
// Calls the useEffect hook if the counter updates
return resetCounter;
}
export default useCustomHook;
© Edunet Foundation. All rights reserved. | 239
To use the custom hook in your components just import the “useCustomHook” function
from “useCustomHook.js” file in the “src” folder.
ComponentA.js:
import React from "react";
// importing the custom hook
import useCustomHook from "./useCustomHook";
function ComponentA(props){
// ClickedButton = resetCounter;
const clickedButton = useCustomHook(0 , "ComponentA");
return (
<div>
<h1> Click on Component A:
to know more details
</h1>
<button onClick={clickedButton}>
Click here!
</button>
</div>
);
}
export default ComponentA;
ComponentB.js:
import React from "react";
// Importing the custom hook
import useCustomHook from "./useCustomHook";
function ComponentB(props){
// ClickedButton = resetCounter;
const clickedButton = useCustomHook(0 , "ComponentB");
return (
<div>
<h1> Click on Component B:
to know more details</h1>
<button onClick={clickedButton}>
© Edunet Foundation. All rights reserved. | 240
Click here!
</button>
</div>
);
}
export default ComponentB;
App.js:
import React from 'react';
import './App.css';
import ComponentA from './components/ComponentA';
import ComponentB from './components/ComponentB';
function App(){
return(
<div className='App'>
<ComponentA />
<ComponentB />
</div>
);
}
export default App;
Output:
© Edunet Foundation. All rights reserved. | 241
Explanation:
The `useEffect` is invoked after the initial render, even if a dependency array is
specified. This implies that the callback function provided to the `useEffect` hook
executes after the first render and subsequently whenever the variables in the
dependency array change. It is important to understand that there is no inherent way
to prevent this initial execution.
Regarding the counters defined in “useCustomHook”, each component has its distinct
counter. The two components utilize different state variables for their counters (as
seen in “useCustomHook.js”), meaning they do not share state. Thus, in this React
application, each component manages its own independent “counter” state variable.
In the same vein, each component's `useEffect` operates independently. If the counter
of `ComponentA` changes, the `useEffect` associated with `ComponentA` is triggered.
Similarly, if the counter of `ComponentB` changes, the `useEffect` for `ComponentB`
is triggered, without affecting `ComponentA`. This independence ensures that the side
effects in each component are managed separately, as evidenced by the behavior
shown in the output.
Guidelines for Creating React Custom Hooks:
Naming Convention: Custom hooks should begin with “use” to adhere to
naming conventions and indicate their use of React hooks.
Encapsulating Stateful Logic: Custom hooks typically encapsulate stateful
logic, making it easy to reuse across multiple components.
Function Nature: Custom hooks are functions containing reusable logic, not
components, making them versatile and easy to integrate into various parts of
your application.
Adherence to React Hook Rules: When using other hooks within custom
hooks, ensure they follow React hook rules, such as maintaining the correct
order and dependency arrays.
© Edunet Foundation. All rights reserved. | 242
Modularity and Code Organization: Custom hooks should focus on
encapsulating a specific concern, promoting modularity, and improving code
organization within React applications.
5.1.3 Understanding useRef in React
The useRef hook in React provides a way to create a mutable object that persists for
the lifetime of the component. It can be used to access and interact with DOM
elements directly, and to hold any mutable value that doesn’t cause a re-render when
updated.
Example: useRef
Focusing on an Input Field
import React, { useRef } from 'react';
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// Access the input element and focus it
inputEl.current.focus();
};
return (
<div>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</div>
);
}
export default TextInputWithFocusButton;
Output:
© Edunet Foundation. All rights reserved. | 243
Explanation:
Creating a Ref:
const inputEl = useRef(null);
useRef(null) initializes a ref object with the current property set to null.
Attaching Ref to an Element:
<input ref={inputEl} type="text" />
The ref attribute is used to attach the inputEl ref to the input element.
Using the Ref:
const onButtonClick = () => {
inputEl.current.focus();
};
inputEl.current accesses the DOM element directly to call the focus method.
Advantages of useRef:
Direct DOM Manipulation: Allows direct interaction with DOM elements
without triggering re-renders.
Persistent Value: Maintains the same object throughout the component's
lifecycle.
Performance: Avoids unnecessary re-renders when updating the ref value.
Disadvantages of useRef:
Imperative Code: Leads to more imperative code, which can be harder to
reason about compared to declarative code.
Misuse: Can be misused for state management, leading to bugs and harder-
to-maintain code.
Features of useRef:
Initial Value: Accepts an initial value, which can be any value (e.g., null, object,
number).
Mutable current Property: The current property can be read and updated
without causing re-renders.
© Edunet Foundation. All rights reserved. | 244
Persistent Object: The ref object is persistent and does not change between
renders.
Conclusion:
The useRef hook is a versatile and powerful tool in React for handling mutable values
and direct DOM manipulation. It provides a way to interact with the DOM without
causing re-renders, making it ideal for scenarios like managing focus, accessing child
elements, and storing mutable values. While it has its advantages, it's important to use
useRef judiciously to maintain clean and maintainable code.
5.1.4 Understanding useReducer in React
The useReducer hook in React is a powerful way to manage state in complex
components. It is an alternative to useState and is particularly useful when the state
logic involves multiple sub-values or when the next state depends on the previous
state.
Example of useReducer
Counter with Increment and Decrement
Code:
import React, { useReducer } from 'react';
// Define the initial state
const initialState = { count: 0 };
// Define the reducer function
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
<button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
</div>
© Edunet Foundation. All rights reserved. | 245
);
}
export default Counter;
Output:
Explanation
Initial State:
const initialState = { count: 0 };
Defines the initial state of the component.
Reducer Function:
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
Defines how the state changes in response to different actions.
Using useReducer:
const [state, dispatch] = useReducer(reducer, initialState);
useReducer takes the reducer function and the initial state, returning the current state
and a dispatch function.
Dispatching Actions:
<button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
<button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
Advantages of useReducer:
Complex State Logic: Ideal for managing complex state logic involving
multiple sub-values.
© Edunet Foundation. All rights reserved. | 246
Predictable State Updates: Ensures state transitions are predictable and easy
to follow.
Decoupling Logic from Components: State management logic is decoupled
from the component, making it easier to test and maintain.
Disadvantages of useReducer:
Boilerplate Code: Can introduce more boilerplate code compared to useState.
Complexity: Might be overkill for simple state management needs.
Learning Curve: Requires understanding of reducers and actions, which might
be complex for beginners.
Features of useReducer:
State Initialization: Accepts an initial state and an optional initializer function.
Reducer Function: A pure function that determines state changes based on
action types.
Dispatch Function: Allows dispatching of actions to trigger state updates.
Conclusion:
The useReducer hook is a robust tool for managing complex state logic in React
applications. It provides a structured approach to handling state transitions, making
state updates predictable and maintainable. While it may introduce some boilerplate
and complexity, its advantages in managing complex state scenarios make it a
valuable addition to the React developer's toolkit. Understanding useReducer can
significantly enhance your ability to manage state in more intricate applications.
5.1.5 Understanding useMemo in React
React, a popular JavaScript library for building user interfaces, provides several hooks
to manage state and lifecycle features in function components. One such hook is
useMemo, which optimizes performance by memoizing values. useMemo is used to
memoize the result of a function and recompute it only when its dependencies change.
This can help avoid expensive calculations on every render, thereby improving the
efficiency of your application.
Explanation of useMemo
The useMemo hook is used to memoize a value so that it is only recalculated when its
dependencies change. This means that if the dependencies do not change, useMemo
will return the memoized value from the previous render, saving computation time.
Syntax:
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
The first argument is a function that computes the value.
The second argument is an array of dependencies that, when changed, will
trigger the function to recompute the value.
Example: Expensive Calculator
Code:
© Edunet Foundation. All rights reserved. | 247
import React, { useState, useMemo } from 'react';
const App = () => {
const [count, setCount] = useState(0);
const [value, setValue] = useState(0);
const expensiveCalculation = (num) => {
console.log('Calculating...');
for (let i = 0; i < 1000000000; i++) {} // Simulate a heavy computation
return num * 2;
};
const memoizedValue = useMemo(() => expensiveCalculation(value), [value]);
return (
<div>
<h1>useMemo Example</h1>
<p>Count: {count}</p>
<p>Value: {value}</p>
<p>Expensive Calculation: {memoizedValue}</p>
<button onClick={() => setCount(count + 1)}>Increment Count</button>
<button onClick={() => setValue(value + 1)}>Increment Value</button>
</div>
);
};
export default App;
Output:
© Edunet Foundation. All rights reserved. | 248
In this example:
expensiveCalculation is a function that simulates a heavy computation.
memoizedValue uses useMemo to store the result of expensiveCalculation and
only recalculates it when value changes.
Clicking "Increment Count" does not trigger the recalculation of
expensiveCalculation, but clicking "Increment Value" does.
Advantages of useMemo:
Performance Optimization: Prevents expensive calculations on every render.
Efficiency: Helps in optimizing components that rely on heavy computations or
complex logic.
Improved Responsiveness: Reduces lag in UI updates by avoiding
unnecessary recalculations.
Disadvantages of useMemo:
Overhead: Introducing useMemo where it is not needed can add unnecessary
overhead.
Complexity: May make the code harder to read and maintain if overused or
misused.
Memory Usage: Memoized values are stored in memory, which can increase
memory usage if not managed properly.
Conclusion:
useMemo is a powerful React hook that can significantly enhance performance by
memoizing values and avoiding unnecessary recalculations. However, it should be
used judiciously, only in cases where the benefits outweigh the additional complexity
and overhead. Proper understanding and application of useMemo can lead to more
efficient and responsive React applications.
5.1.6 Understanding usecallback in React
React, a widely-used JavaScript library for building user interfaces, offers various
hooks to manage state and side effects in function components. One essential hook
is useCallback, which helps in optimizing performance by memoizing functions.
useCallback is used to return a memoized version of a callback function that only
changes if one of its dependencies has changed. This is particularly useful in
scenarios where passing callback functions as props could cause unnecessary re-
renders.
Explanation of useCallback
The useCallback hook is used to memoize a function, ensuring that the same instance
of the function is returned as long as its dependencies remain unchanged. This
prevents the creation of new function instances on every render, which can be
beneficial for performance, especially in child components that rely on the function.
Syntax:
© Edunet Foundation. All rights reserved. | 249
const memoizedCallback = useCallback(() => {
doSomething(a, b);
}, [a, b]);
The first argument is the function you want to memoize.
The second argument is an array of dependencies that, when changed, will
cause the function to be recreated.
Example: Increment Count and Value
Code:
import React, { useState, useCallback } from 'react';
const ChildComponent = React.memo(({ onButtonClick }) => {
console.log('ChildComponent rendered');
return <button onClick={onButtonClick}>Click me</button>;
});
const App = () => {
const [count, setCount] = useState(0);
const [value, setValue] = useState(0);
const handleButtonClick = useCallback(() => {
console.log('Button clicked');
}, [value]);
return (
<div>
<h1>useCallback Example</h1>
<p>Count: {count}</p>
<p>Value: {value}</p>
<ChildComponent onButtonClick={handleButtonClick} />
<button onClick={() => setCount(count + 1)}>Increment Count</button>
<button onClick={() => setValue(value + 1)}>Increment Value</button>
</div>
);
};
export default App;
Output:
© Edunet Foundation. All rights reserved. | 250
In this example:
ChildComponent is a memoized component that receives a callback function
as a prop.
handleButtonClick is a memoized function created using useCallback, which
only changes when value changes.
Clicking "Increment Count" does not cause ChildComponent to re-render,
but clicking "Increment Value" does.
Advantages of useCallback:
Performance Optimization: Helps prevent unnecessary re-renders by
ensuring stable function references.
Efficiency: Reduces the number of times child components re-render,
improving performance.
Improved Code Readability: Clearly shows the intention of preventing
unnecessary function recreations.
Disadvantages of useCallback:
Overhead: Using useCallback unnecessarily can add complexity and slight
performance overhead.
Complexity: Can make the code harder to read and maintain if overused or
applied incorrectly.
Memory Usage: Memoized functions are stored in memory, which can
increase memory usage if not managed properly.
Conclusion:
useCallback is a valuable React hook that enhances performance by memoizing
functions and preventing unnecessary re-renders. However, it should be used
judiciously, ensuring that the benefits outweigh the potential overhead and complexity.
Proper understanding and application of useCallback can lead to more efficient and
performant React applications, particularly in scenarios involving complex child
component structures and frequent prop changes
© Edunet Foundation. All rights reserved. | 251
5.2 Page Routing
Introduction to React Router:
React Router is a popular third-party library used to add routing to React applications.
Unlike traditional websites, which send requests to the server for routing, React Router
works as a single-page application (SPA). To navigate between different views or
components without refreshing the entire web page. This enhances the user
experience by providing smooth transitions and faster load times. It handles all routing
on the frontend without additional server requests.
Routing allows users to move between different parts of an application by entering a
URL or clicking elements (links, buttons, etc.).
Key Terminology:
BrowserRouter: Wraps the entire application and manages the application’s
location. Routes are defined within it.
Routes: Contains child routes and determines which UI branch to render based
on the application’s location.
Route: Renders a component when the user navigates to a specific path.
Link: Similar to an HTML <a> tag, it allows navigation between pages without
page reload.
NavLink: A special type of <Link> that points to the currently selected location.
Features of React Router:
Declarative Routing: Routes are declared in the JSX code, making them easy
to read and manage.
Nested Routes: Support for nested routes allows structuring routes
hierarchically.
Dynamic Routing: Routes can be generated dynamically based on the
application's state.
URL Parameters: Allows capturing URL parameters to pass data between
routes.
Redirects: Ability to redirect from one route to another.
Example:
Develop an enhanced React application that includes educational content related to
the Edunet Foundation, with visually appealing styling and navigation.
Code:
public/page.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
© Edunet Foundation. All rights reserved. | 252
<title>Edunet Foundation - TechSaksham Program</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<h2>Welcome to Edunet Foundation</h2>
<p>Edunet Foundation is committed to providing quality education to
underprivileged students. Our goal is to empower the youth with skills
necessary for the future through our TechSaksham program.</p>
<h3>About TechSaksham Program</h3>
<p>The TechSaksham program offers cutting-edge courses designed to equip
students with the skills required to excel in the tech industry. Our focus
areas include Artificial Intelligence and MERN Stack Development.</p>
<h3>Artificial Intelligence</h3>
<p>Our AI course covers various topics including machine learning,
neural networks, and data analysis. Students will learn how to build
intelligent systems that can make decisions and perform tasks
autonomously.</p>
<img src="https://via.placeholder.com/300?text=AI+Course"
alt="Artificial Intelligence Course" class="course-image">
<h3>MERN Stack Development</h3>
<p>Our MERN Stack course teaches full-stack development using MongoDB,
Express.js, React, and Node.js. Students will gain hands-on experience in
building scalable web applications.</p>
<img src="https://via.placeholder.com/300?text=MERN+Stack+Course"
alt="MERN Stack Course" class="course-image">
</div>
</body>
</html>
public/style.css:
body {
font-family: Arial, sans-serif;
background-color: #f9f9f9;
margin: 0;
padding: 20px;
}
.container {
max-width: 800px;
margin: auto;
background-color: #ffffff;
padding: 20px;
© Edunet Foundation. All rights reserved. | 253
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
h2 {
color: #2c3e50;
text-align: center;
}
h3 {
color: #34495e;
margin-top: 20px;
}
p {
color: #7f8c8d;
line-height: 1.6;
}
.course-image {
width: 100%;
max-width: 300px;
display: block;
margin: 10px auto;
border-radius: 8px;
}
src/components/Home.js:
import React from 'react';
const Home = () => {
return (
<div>
<h2>Welcome to Edunet Foundation</h2>
<p>Edunet Foundation is dedicated to providing quality education to
underprivileged students and empowering them with the skills needed for the
future.</p>
<p>Our TechSaksham program offers cutting-edge courses in Artificial
Intelligence and MERN Stack development.</p>
</div>
);
};
export default Home;
src/components/About.js:
import React from 'react';
© Edunet Foundation. All rights reserved. | 254
const About = () => {
return (
<div>
<h2>About Edunet Foundation</h2>
<p>Edunet Foundation is a social enterprise which was founded in 2015
and focuses on bridging the academia-industry divide, enhancing student
employability, promoting innovation and creating an entrepreneurial
ecosystem in India. Working primarily with emerging technologies, and
striving to leverage them to augment, upgrade the knowledge ecosystem and
equip the beneficiaries to become contributors themselves, we work
extensively to build a workforce with an IR 4.0 enabled career.</p>
<p>The organization has enjoyed Special Consultative Status with the
Economic and Social Council (ECOSOC) of the United Nations since 2020. With
a national footprint, EF’s programs, online and instructor-led, benefit tens
of thousands of learners every year.</p>
</div>
);
};
export default About;
src/components/Contact.js:
import React from 'react';
const Contact = () => {
return (
<div>
<h2>Contact Us</h2>
<h2>Get in Touch</h2>
<p>Have any doubts? Want to speak to us? Just reach out and we will
get back to you as soon as possible!</p>
<ul>
<li>
<h3>Gurgaon/NCR office</h3>
<p>A-11-1105, Arcadia,South City 2, Gurgaon 122018, India</p></li>
<li>
<h3>E-mail</h3>
<p>
[email protected]</p></li>
</ul>
</div>
);
};
© Edunet Foundation. All rights reserved. | 255
export default Contact;
src/components/Courses.js:
import React from 'react';
const Courses = () => {
return (
<div>
<h2>Courses Offered</h2>
<h3>TechSaksham Program</h3>
<h4>Artificial Intelligence</h4>
<p>Our AI course covers the basics to advanced topics in Artificial
Intelligence, including machine learning, neural networks, and data
analysis.</p>
<h4>MERN Stack</h4>
<p>Learn full-stack development with our comprehensive MERN Stack
course, covering MongoDB, Express.js, React, and Node.js.</p>
</div>
);
};
export default Courses;
src/components/HtmlPage.js:
import React from 'react';
const HtmlPage = () => {
return (
<div>
<iframe src="/page.html" title="HTML Page" width="100%" height="600px"
style={{ border: 'none' }}></iframe>
</div>
);
};
export default HtmlPage;
src/App.js:
import React from 'react';
import { BrowserRouter as Router, Route, Routes, Link } from 'react-router-
dom';
import Home from './components/Home';
import About from './components/About';
import Contact from './components/Contact';
import Courses from './components/Courses';
import HtmlPage from './components/HtmlPage';
import './App.css';
© Edunet Foundation. All rights reserved. | 256
const App = () => {
return (
<Router>
<div>
<nav>
<button><Link to="/">Home</Link></button>
<button><Link to="/about">About</Link></button>
<button><Link to="/contact">Contact</Link></button>
<button><Link to="/courses">Courses</Link></button>
<button><Link to="/html">HTML Page</Link></button>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
<Route path="/courses" element={<Courses />} />
<Route path="/html" element={<HtmlPage />} />
</Routes>
</div>
</Router>
);
};
export default App;
src/App.css:
body {
font-family: Arial, sans-serif;
background-color: #f9f9f9;
margin: 0;
padding: 20px;
}
h2 {
color: #2c3e50;
}
h3 {
color: #34495e;
}
h4 {
color: #16a085;
}
© Edunet Foundation. All rights reserved. | 257
p, ul, li {
color: #7f8c8d;
}
nav {
margin-bottom: 20px;
}
button {
background-color: #3498db;
color: white;
border: none;
padding: 10px 20px;
margin: 5px;
cursor: pointer;
border-radius: 5px;
}
button a {
color: white;
text-decoration: none;
}
button:hover {
background-color: #2980b9;
}
iframe {
border-radius: 5px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
Output:
© Edunet Foundation. All rights reserved. | 258
© Edunet Foundation. All rights reserved. | 259
Explanation:
1. Import Statements:
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';
Router wraps your entire application and enables routing.
Route defines a mapping between a URL path and a component.
Switch renders the first child Route that matches the location.
Link is used to create navigation links that don’t reload the page.
2. Components:
We have three components: Home, About, and Contact.
Each component returns a simple message.
3. Router Setup:
The Router component wraps the entire application.
The nav section contains navigation links using the Link component to avoid
full page reloads.
The Switch component ensures that only one Route is rendered at a time. It
tries to match the URL with the path specified in each Route component.
The Route components define the paths and the components to render for
those paths. For example, Route exact path="/" component={Home} means the
Home component will be rendered when the URL path is /.
4. HTML and CSS Files
These files are located in the public directory and are used to create the static
HTML page and styles.
This HTML file provides an overview of the Edunet Foundation and its
TechSaksham program, including sections for Artificial Intelligence and MERN
Stack courses. It includes placeholder images to visually represent the courses.
This CSS file styles the content in page.html, ensuring a clean and professional
look with specific styles for headings, paragraphs, and images.
5. React Components
React components are created in the src/components directory.
The Home component provides an introduction to the Edunet Foundation and
the TechSaksham program.
The About component describes the mission and initiatives of the Edunet
Foundation.
© Edunet Foundation. All rights reserved. | 260
The Contact component provides contact information for the Edunet
Foundation.
The Courses component provides details about the courses offered under the
TechSaksham program.
The HtmlPage component uses an iframe to load the static HTML page
(page.html), which contains detailed information and images related to the
Edunet Foundation's educational programs.
The App component sets up the Router and defines routes for each page. It
includes a navigation bar with buttons linking to different routes. The Routes
component renders the appropriate component based on the URL path.
Advantages of Page Routing:
State
Management
Improved Advantages of Faster
User
Page routing Navigation
Experience
SEO Friendly
Figure 78. Advantages of Page Routing
Improved User Experience: Smooth transitions between pages without full
page reloads.
Faster Navigation: Only the content of the component changes, leading to
faster load times.
SEO Friendly: With server-side rendering, React Router can help improve
SEO.
State Management: Easier to manage state across different components.
© Edunet Foundation. All rights reserved. | 261
Disadvantages of Page Routing:
Initial
Load
Complexit Time
y
SEO
Challenges
Disadvantages of Page
Routing
Complexity: Managing routes and nested routes can become complex in
larger applications.
Initial Load Time: The initial load time may be higher since the entire
JavaScript bundle is downloaded.
SEO Challenges: Without server-side rendering, client-side routing can be
challenging for SEO.
When to Use Page Routing in Real Time:
Single Page Applications (SPAs): For applications where the user navigates
between different views without full page reloads.
Dashboards: For admin panels or dashboards where multiple views (e.g.,
reports, settings) need to be accessed.
E-commerce Websites: Where users navigate between different product
categories, details, and carts.
Content Management Systems (CMS): For websites with structured content
that needs to be displayed across different pages.
Portfolios: Personal or business portfolios where different sections (e.g.,
About, Projects, Contact) are shown.
Conclusion:
React Router is an essential tool for building seamless, navigable React applications.
Its ability to handle complex routing structures, manage navigation state, and integrate
with React's component-based architecture makes it invaluable for modern web
development. However, weighing its benefits against potential complexities is crucial,
especially in large-scale applications.
© Edunet Foundation. All rights reserved. | 262
5.3 Optimizing performance
Optimizing performance in React involves several techniques aimed at reducing
unnecessary renders, improving the efficiency of component updates, and managing
resource-intensive operations.
1. Avoid Inline Functions
Inline functions cause components to re-render because a new function instance is
created on every render. Use useCallback or class methods to avoid this.
Before Optimization:
<button onClick={() => handleClick(id)}>Click</button>
After Optimization:
const memoizedHandleClick = useCallback(() => handleClick(id), [id]);
<button onClick={memoizedHandleClick}>Click</button>
2. Efficient State Management
Keep state as minimal and local as possible to avoid unnecessary re-renders. Lift state
up only when necessary.
Code:
const ParentComponent = () => {
const [count, setCount] = useState(0);
const [name, setName] = useState('');
return (
<>
<ChildComponent count={count} setCount={setCount} />
<AnotherChildComponent name={name} setName={setName} />
</>
);
};
3. Optimizing Lists with React.Fragment and key Prop
Use React.Fragment to avoid adding extra nodes to the DOM and ensure each list
item has a unique key prop.
Code:
import React from 'react';
const ListComponent = ({ items }) => (
<ul>
{items.map(item => (
© Edunet Foundation. All rights reserved. | 263
<React.Fragment key={item.id}>
<li>{item.name}</li>
</React.Fragment>
))}
</ul>
);
4. Avoid Anonymous Functions in JSX
Passing anonymous functions directly in JSX can cause performance issues. Use
class methods or memoized functions instead.
Code:
Before Optimization:
<button onClick={() => handleClick(item.id)}>Click</button>
After Optimization:
const handleClick = useCallback((id) => {
// handle click
}, []);
<button onClick={() => handleClick(item.id)}>Click</button>
5. Using React.memo
React.memo is a higher-order component that memoizes a functional component,
preventing it from re-rendering unless its props change.
Code:
import React, { useState } from 'react';
const ChildComponent = React.memo(({ value }) => {
console.log('ChildComponent rendered');
return <div>{value}</div>;
});
const App = () => {
const [count, setCount] = useState(0);
const [value, setValue] = useState(0);
return (
<div>
<ChildComponent value={value} />
<button onClick={() => setCount(count + 1)}>Increment Count</button>
<button onClick={() => setValue(value + 1)}>Increment Value</button>
</div>
);
};
© Edunet Foundation. All rights reserved. | 264
export default App;
Output:
In this example, ChildComponent will only re-render when the value prop changes, not
when the count state changes.
6. Using useMemo
useMemo memoizes a value, recomputing it only when its dependencies change. This
can be useful for expensive calculations.
Code:
import React, { useState, useMemo } from 'react';
const App = () => {
const [value, setValue] = useState(0);
const expensiveCalculation = (num) => {
console.log('Calculating...');
for (let i = 0; i < 1000000000; i++) {} // Simulate a heavy computation
return num * 2;
};
const memoizedValue = useMemo(() => expensiveCalculation(value), [value]);
return (
<div>
<p>Value: {value}</p>
<p>Memoized Calculation: {memoizedValue}</p>
<button onClick={() => setValue(value + 1)}>Increment Value</button>
</div>
);
};
export default App;
Output:
© Edunet Foundation. All rights reserved. | 265
Here, expensiveCalculation is only recalculated when value changes, reducing
unnecessary computations.
© Edunet Foundation. All rights reserved. | 266
5.4 Code splitting and lazy loading
Code splitting and lazy loading are essential techniques for optimizing the
performance of React applications. They help reduce the initial load time by splitting
the application into smaller bundles and loading them on demand.
5.4.1 Code Splitting:
Code splitting is the process of breaking down your application into smaller chunks,
which can then be loaded on demand. This reduces the size of the initial bundle and
improves load times.
Using Dynamic import():
Dynamic import() is a feature in JavaScript that allows you to load modules
asynchronously.
Code:
import React, { Suspense, lazy } from 'react';
const OtherComponent = lazy(() => import('./OtherComponent'));
const App = () => (
<div>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
</div>
);
export default App;
In this example, OtherComponent is only loaded when it is rendered, thanks to the
dynamic import() and React.lazy.
Code Splitting with React Router:
When using React Router, you can take advantage of code splitting to load routes
lazily.
Code:
import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
// Lazy load route components
const Home = lazy(() => import('./Home'));
const About = lazy(() => import('./About'));
const Contact = lazy(() => import('./Contact'));
const App = () => (
© Edunet Foundation. All rights reserved. | 267
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
</Switch>
</Suspense>
</Router>
);
export default App;
In this example, each route component (Home, About, Contact) is lazily loaded when
the route is matched, reducing the initial bundle size.
Conclusion:
Optimizing performance in React applications involves a combination of efficient
component design and the strategic use of hooks and techniques. By employing
React.memo, useMemo, useCallback, efficient state management and avoiding
unnecessary re-renders, you can significantly enhance the performance of your React
applications. Properly applied, these strategies lead to faster, more responsive user
interfaces and an overall better user experience.
5.4.2 Lazy Loading:
Lazy loading delays the loading of components until they are needed. This can
significantly improve the performance of your application, especially when you have
large components or routes that are not needed immediately.
Using React.lazy and Suspense
React.lazy allows you to define a component that is loaded lazily. Suspense is used
to wrap the lazy-loaded component and provide a fallback while it is loading.
Code:
import React, { Suspense, lazy } from 'react';
// Lazy load the component
const LazyComponent = lazy(() => import('./LazyComponent'));
const App = () => (
<div>
<h1>Main Application</h1>
{/* Suspense component to show a fallback while loading */}
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
</div>
© Edunet Foundation. All rights reserved. | 268
);
export default App;
Error Boundaries with Lazy Loading
When using React.lazy, it is recommended to use an error boundary to catch potential
errors during the lazy loading process.
Code:
import React, { Suspense, lazy, Component } from 'react';
const LazyComponent = lazy(() => import('./LazyComponent'));
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
console.log(error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
const App = () => (
<ErrorBoundary>
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
</ErrorBoundary>
);
export default App;
© Edunet Foundation. All rights reserved. | 269
Conclusion:
Code splitting and lazy loading are powerful techniques to optimize the performance
of React applications by reducing the initial load time and loading components on
demand. Using React.lazy and Suspense, along with dynamic import(), enables you
to break down your application into smaller, more manageable chunks. When
combined with React Router, these techniques provide a seamless and efficient way
to improve the performance and user experience of your application.
© Edunet Foundation. All rights reserved. | 270
5.5 Introduction of Redux:
React Redux is a library that provides bindings to use Redux with React applications.
Redux is a predictable state container for JavaScript apps, often used with React for
managing application state in a more predictable and centralized way.
Advantages of React Redux:
Predictable
Centralized Time Travel Server-side Middleware
State
State Debugging Rendering Support
Management
Figure 79. Advantages of React Redux
Predictable State Management: Since the state is managed in a single place
(the store), the application state becomes predictable, making debugging and
testing easier.
Centralized State: All state transformations are centralized, leading to more
maintainable and scalable code.
Time Travel Debugging: Redux DevTools allow developers to time travel
through state changes, which can be very useful for debugging.
Server-side Rendering: Simplifies server-side rendering, which can be
important for SEO and performance.
Middleware Support: Easy to extend with middleware like redux-thunk or
redux-saga for handling asynchronous operations and side effects.
© Edunet Foundation. All rights reserved. | 271
Disadvantages of React Redux:
Boilerplate
Overhead
for Small
Learning
Curve
Code
Apps
Figure 80. Disadvantages of React Hooks
Boilerplate Code: Setting up Redux can involve writing a lot of boilerplate
code, including actions, reducers, and action creators.
Learning Curve: The concepts of Redux (actions, reducers, store,
middleware) can be challenging for beginners to grasp.
Overhead for Small Apps: For small applications, Redux might be overkill,
adding unnecessary complexity.
5.5.1 Setting up Redux with React
Setting up Redux with React can significantly enhance your application's state
management capabilities. Here's a step-by-step guide to integrate Redux into a React
application:
Step 1: Create a React Application
First, create a new React application using create-react-app if you haven't
already.
npx create-react-app my-redux-app
cd my-redux-app
Step 2: Install Redux and React-Redux
Next, install redux and react-redux packages.
npm install redux react-redux
Step 3: Set Up Redux Store
Create a file for your Redux store. The store holds the complete state tree of
your application.
Create a new directory called store inW the src folder.
create a file named index.js.
© Edunet Foundation. All rights reserved. | 272
In src/store/index.js, set up your Redux store.
// src/store/index.js
import { createStore } from 'redux';
import rootReducer from '../reducers';
const store = createStore(
rootReducer,
window.__REDUX_DEVTOOLS_EXTENSION__ &&
window.__REDUX_DEVTOOLS_EXTENSION__()
);
export default store;
Step 4: Create a Root Reducer
Reducers specify how the application's state changes in response to actions sent to
the store.
Create a new directory called reducers in the src folder.
Inside the reducers directory, create a file named index.js.
In src/reducers/index.js, define your root reducer.
// src/reducers/index.js
import { combineReducers } from 'redux';
// import your reducers here
const rootReducer = combineReducers({
// add your reducers here
});
export default rootReducer;
Step 5: Create Reducers
Create specific reducers based on your application needs.
Inside the reducers directory, create a file named exampleReducer.js.
In src/reducers/exampleReducer.js, define your reducer.
// src/reducers/exampleReducer.js
const initialState = {
exampleState: []
};
const exampleReducer = (state = initialState, action) => {
switch (action.type) {
case 'ADD_EXAMPLE':
return {
...state,
© Edunet Foundation. All rights reserved. | 273
exampleState: [...state.exampleState, action.payload]
};
default:
return state;
}
};
export default exampleReducer;
Import and add this reducer to your root reducer.
// src/reducers/index.js
import { combineReducers } from 'redux';
import exampleReducer from './exampleReducer';
const rootReducer = combineReducers({
example: exampleReducer
});
export default rootReducer;
Step 6: Provide the Redux Store to Your React Application
Wrap your application with the Provider component to make the Redux store available
to your React components.
In src/index.js, import the Provider from react-redux and the store.
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './store';
import App from './App';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
Step 7: Connect Your Components to the Redux Store
Use the useSelector and useDispatch hooks from react-redux to interact with the
Redux store within your components.
In any React component (e.g., App.js), use these hooks to access state and
dispatch actions.
© Edunet Foundation. All rights reserved. | 274
// src/App.js
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
function App() {
const exampleState = useSelector(state => state.example.exampleState);
const dispatch = useDispatch();
const addExample = (example) => {
dispatch({ type: 'ADD_EXAMPLE', payload: example });
};
return (
<div>
<h1>Redux Example</h1>
<button onClick={() => addExample('In Redux, reducers are pure functions that
handle state logic, accepting the initial state and action type to update and
return the state, facilitating changes in React view components.
(State,action) => newState. ')}>
Click on Reducer
</button>
<ul>
{exampleState.map((example, index) => (
<li key={index}>{example}</li>
))}
</ul>
</div>
);
}
export default App;
Step 8: Testing
Run your application to ensure everything is set up correctly.
npm start
© Edunet Foundation. All rights reserved. | 275
Output:
© Edunet Foundation. All rights reserved. | 276
5.6 Understand about Actions, reducers, and the store
Redux is a state management library commonly used with React. It helps manage the
state of your application in a predictable way. The core concepts in Redux are actions,
reducers, and the store.
Actions: Actions are plain JavaScript objects that represent an event or change
in the state. They must have a type property, which indicates the type of action
being performed, and they can also include additional data.
Reducers: Reducers are pure functions that take the current state and an
action as arguments and return a new state. They specify how the application's
state changes in response to actions.
Store: The store holds the whole state tree of your application. It allows access
to the state via getState(), allows state to be updated via dispatch(action), and
registers listeners via subscribe(listener).
Directory Structure:
my-redux-app/
├── public/
├── src/
│ ├── actions/
│ │ └── counterActions.js
│ ├── components/
│ │ └── Counter.js
│ ├── reducers/
│ │ └── counterReducer.js
│ ├── store/
│ │ └── store.js
│ ├── actionTypes.js
│ ├── App.js
│ ├── index.js
│ └── index.css
├── package.json
└── README.md
1. Action Types:
File: src/actionTypes.js
// actionTypes.js
export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';
2. Actions:
File: src/actions/counterActions.js
// actions/counterActions.js
import { INCREMENT, DECREMENT } from '../actionTypes';
© Edunet Foundation. All rights reserved. | 277
export const increment = () => ({
type: INCREMENT
});
export const decrement = () => ({
type: DECREMENT
});
3. Reducer:
File: src/reducers/counterReducer.js
// reducers/counterReducer.js
import { INCREMENT, DECREMENT } from '../actionTypes';
const initialState = {
count: 0
};
const counterReducer = (state = initialState, action) => {
switch (action.type) {
case INCREMENT:
return {
...state,
count: state.count + 1
};
case DECREMENT:
return {
...state,
count: state.count - 1
};
default:
return state;
}
};
export default counterReducer;
4. Store:
File: src/store/store.js
// store/store.js
import { createStore } from 'redux';
import counterReducer from '../reducers/counterReducer';
const store = createStore(counterReducer);
© Edunet Foundation. All rights reserved. | 278
export default store;
5. Counter Component:
File: src/components/Counter.js
// components/Counter.js
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement } from '../actions/counterActions';
const Counter = () => {
const count = useSelector(state => state.count);
const dispatch = useDispatch();
return (
<div>
<h1>{count}</h1>
<button onClick={() => dispatch(increment())}>Increment</button>
<button onClick={() => dispatch(decrement())}>Decrement</button>
</div>
);
};
export default Counter;
6. App Component:
File: src/App.js
// App.js
import React from 'react';
import Counter from './components/Counter';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<Counter />
</header>
</div>
);
}
export default App;
7. Index File:
File: src/index.js
// index.js
© Edunet Foundation. All rights reserved. | 279
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import store from './store/store';
import App from './App';
import './index.css';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<App />
</Provider>
);
Output:
Features of Redux in this Application:
Predictable State: The state is predictable because it is managed by reducers.
Centralized State Management: All state is stored in a single place (Redux
store).
Debuggable: Tools like Redux DevTools can be used to trace actions, inspect
state, and debug the application.
Maintainable: Clear structure of actions, reducers, and store helps in
maintaining and scaling the application.
© Edunet Foundation. All rights reserved. | 280
Advantages:
Predictability: The state behaves predictably due to the strict structure.
Ease of Testing: Pure functions and structured Redux make testing
straightforward.
Debugging Tools: Redux DevTools provides powerful tools for debugging.
Decoupling: Actions and reducers decouple state management logic from UI
components.
Disadvantages:
Boilerplate Code: Redux can introduce a lot of boilerplate code.
Learning Curve: Steeper learning curve for beginners.
Overhead for Small Apps: Complexity introduced by Redux might not be
justified for small apps.
Performance: Frequent state updates can lead to performance bottlenecks if
not handled properly.
Conclusion:
Redux is a powerful state management tool for React applications, providing
predictability, maintainability, and powerful debugging capabilities. However, it
introduces complexity and boilerplate code, making it potentially overkill for smaller
applications. The decision to use Redux should be based on the scale and
requirements of your application.
Overall, Redux remains a popular choice for managing state in large-scale React
applications due to its predictable state container and robust tooling ecosystem. The
structured approach it enforces can significantly improve code maintainability and
collaboration in complex applications.
© Edunet Foundation. All rights reserved. | 281
5.7 Using Redux Dev Tools
Redux DevTools is a powerful browser extension and API that helps developers debug
and optimize Redux applications.Let’s break down how to use it step by step:
1.Install the Browser Extension:
For Firefox: https://addons.mozilla.org/en-US/firefox/addon/reduxdevtools/
For Chrome:
https://chromewebstore.google.com/detail/redux-
devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=en&pli=1
Open Redux DevTools:
Open your React application in the browser.
Open the browser's Developer Tools (F12 or right-click -> Inspect).
Find the "Redux" tab, which is added by the Redux DevTools extension.
Inspect Actions and State:
Dispatch actions in your application (e.g., click the increment and decrement
buttons).
Observe the actions and state changes in the "Redux" tab.
You can time travel by selecting an action in the list and seeing the state before
and after that action.
Sample Screenshots:
1.After adding the extension, you can see its icon right next to the URL bar.
Figure 81. View Extension for Redux icon
2. Open the browser's Developer Tools by pressing F12 or right-clicking and selecting
"Inspect".
Figure 82. Action Tab
© Edunet Foundation. All rights reserved. | 282
3. Then click on the Redux icon to access the Redux DevTools with its available
options
Figure 83. Redux Dev Tool options Tab
Advantages of Redux DevTools:
Time-Travel Debugging: Allows you to go back in time and see the state
changes and actions that led to a specific state.
State Inspection: Inspect the state tree at any point in time.
Action Replay: Replay any action to see its effect on the state.
Ease of Debugging: Simplifies identifying and fixing issues.
Middleware Support: Can be used with middleware like Redux Thunk for
handling asynchronous actions.
Disadvantages of Redux DevTools:
Performance Overhead: Can introduce performance overhead, especially in
large applications with frequent state changes.
Security Concerns: In production environments, exposing the Redux
DevTools can be a security risk as it provides insight into the application state
and actions.
© Edunet Foundation. All rights reserved. | 283
Conclusion
Redux DevTools is an invaluable tool for developers working with Redux in React
applications. It provides powerful features for debugging and understanding state
changes, making it easier to identify and fix issues. However, it introduces some
performance overhead and potential security concerns, so it should be used
judiciously, especially in production environments.
By integrating Redux DevTools into your development workflow, you gain deeper
insights into your application's state management, ultimately helping you build more
robust and maintainable applications.
© Edunet Foundation. All rights reserved. | 284
Chapter 6: NodeJS Essentials
Learning Outcomes:
Introduction to Node.js
Introduction to NPM in Node.js
Understanding package. JSON
Working with NPM scripts
Modules in Node.js (Built-in, NPM, User defined)
6.1 Introduction to Node.js
Node.js is an open-source, cross-platform JavaScript runtime environment that allows
developers to execute JavaScript code outside of a web browser. It was initially
released in 2009 by Ryan Dahl and has since grown to become a fundamental tool in
modern web development. Node.js uses an event-driven, non-blocking I/O model,
making it lightweight and efficient, particularly suitable for data-intensive real-time
applications that run across distributed devices.
Figure 84. Nodejs Layered Architecture
ImageSource: https://dev.to/yaariii3/nodejs-layered-architecture-4gk7
© Edunet Foundation. All rights reserved. | 285
Features of Node.js:
Asynchronous and Event-Driven: All APIs in Node.js are asynchronous,
meaning the server does not wait for an API to return data. This feature helps
in handling multiple requests efficiently.
Single-Threaded but Highly Scalable: Node.js uses a single-threaded model
with event looping, which helps in managing a large number of simultaneous
connections with high throughput.
Fast Execution: Built on Google Chrome’s V8 JavaScript engine, Node.js
executes JavaScript code very quickly.
NPM (Node Package Manager): Node.js includes a package manager that
allows developers to manage dependencies easily. NPM has a large repository
of open-source libraries available for developers.
Cross-Platform: Node.js can run on various operating systems, including
Windows, macOS, Linux, and Unix.
Rich Ecosystem: With the extensive module library in NPM, developers have
access to a wide range of tools and utilities that can be easily integrated into
Node.js applications.
Advantages of Node.js:
Figure 85. Advantages of Nodejs
High Performance: Node.js is known for its high performance due to its non-
blocking I/O operations and event-driven architecture.
Scalability: Node.js applications can handle a large number of simultaneous
connections with high throughput, making it suitable for scalable network
applications.
Real-Time Applications: Perfect for applications that require real-time
interaction, such as chat applications, online gaming, and collaborative tools.
© Edunet Foundation. All rights reserved. | 286
Community Support: A strong and active community contributes to continuous
improvement and support for Node.js.
Code Reusability: Sharing and reusing code between the frontend and
backend is possible since both can be written in JavaScript.
Disadvantages of Node.js:
Callback Hell: The heavy use of callbacks can lead to complex, nested code
that is hard to read and maintain, commonly known as "callback hell."
Single-Threaded Limitations: While the single-threaded model is beneficial
for certain tasks, it can be a bottleneck for CPU-intensive operations.
Maturity of Tools: Some tools and libraries in the Node.js ecosystem may lack
maturity compared to those in more established environments.
API Stability: Frequent updates to Node.js can sometimes introduce breaking
changes, affecting the stability of APIs.
Architecture and Design of Node.js:
Figure 86. Design of Node.js
Image Source:https://medium.com/@asiandigitalhub/understanding-the-architecture-of-node-js-
applications-141eaa8c3ba6
Node.js architecture is based on the following key components:
Event Loop: The core of Node.js’s architecture, the event loop processes all
asynchronous operations. It is responsible for handling callbacks, non-blocking
I/O, and managing events.
Single Thread: Node.js runs on a single thread, using non-blocking I/O calls,
allowing it to support tens of thousands of concurrent connections without
incurring the cost of thread context switching.
Libuv: A multi-platform C library that provides support for asynchronous I/O
operations, the event loop, and threading.
© Edunet Foundation. All rights reserved. | 287
V8 Engine: Google’s high-performance JavaScript engine, which compiles
JavaScript code directly to native machine code for fast execution.
C++ Bindings: Node.js uses C++ bindings to leverage the performance of the
underlying system and libraries like libuv and V8.
Modules: Node.js follows a modular architecture, encouraging the
development of self-contained modules that can be easily shared and reused
via NPM.
Conclusion:
Node.js has revolutionized server-side development by enabling JavaScript to be used
for backend programming. Its non-blocking, event-driven architecture makes it
particularly suitable for building scalable and efficient applications, especially those
requiring real-time capabilities. Despite some drawbacks such as callback hell and
single-threaded limitations, the advantages of high performance, scalability, and
strong community support make Node.js a compelling choice for modern web
development. As the ecosystem continues to evolve, Node.js is likely to remain a key
player in the world of software development.
© Edunet Foundation. All rights reserved. | 288
6.2 Introduction to NPM in Node.js:
NPM, which stands for Node Package Manager, is a crucial tool in the Node.js
ecosystem. It serves as the default package manager for Node.js, providing a vast
repository of open-source libraries and tools that developers can use to streamline
their development processes. NPM not only facilitates the installation and
management of dependencies but also aids in the publishing and sharing of Node.js
packages.
Advantages of NPM:
Extensive Package Repository: NPM hosts the world's largest collection of
free, reusable code packages, making it easy to find and use third-party
libraries.
Dependency Management: Automatically handles the installation and
management of project dependencies, ensuring the correct versions are used.
Version Control: Allows developers to specify the versions of packages they
want to use, ensuring consistency across different environments.
Ease of Use: Simple and intuitive command-line interface for installing,
updating, and managing packages.
Custom Scripts: Facilitates the automation of repetitive tasks through custom
scripts defined in the package.json file.
Community Support: A large and active community contributes to a
continually growing repository of packages and provides support through
forums and documentation.
Disadvantages of NPM:
Security Risks: Open-source packages can contain vulnerabilities, and relying
on third-party code may introduce security risks.
Dependency Bloat: Projects can become bloated with dependencies, leading
to larger project sizes and potential maintenance challenges.
Compatibility Issues: Updating packages can sometimes lead to compatibility
issues or breaking changes if not carefully managed.
Performance Overhead: Managing a large number of dependencies can
introduce performance overhead during installation and build processes.
Features of NPM:
Package Installation: npm install allows for easy installation of packages from
the NPM registry.
Dependency Management: NPM automatically manages the dependencies
listed in the package.json file, installing the correct versions.
Versioning: Supports semantic versioning, allowing developers to specify and
control the versions of packages.
Custom Scripts: Allows the definition of custom scripts in the package.json file
to automate tasks like testing, building, and deploying.
Publishing Packages: Provides tools to publish and share packages with the
community or within a private organization.
NPM CLI: The command-line interface offers a wide range of commands for
managing packages, such as npm install, npm update, npm publish, and more.
© Edunet Foundation. All rights reserved. | 289
Conclusion:
NPM is a powerful and essential tool in the Node.js ecosystem, greatly simplifying the
management of project dependencies and the automation of development tasks. Its
extensive package repository, ease of use, and robust features make it an invaluable
resource for developers. While there are some challenges, such as security risks and
dependency management complexities, the benefits of using NPM far outweigh these
disadvantages.
By leveraging NPM, developers can enhance their productivity, maintain consistency
across different environments, and benefit from the vast array of available open-
source packages. As a result, NPM plays a critical role in modern web development,
supporting the growth and innovation of the Node.js community.
© Edunet Foundation. All rights reserved. | 290
6.3 Understanding Package.json:
The package.json file is a crucial component in a Node.js project. It serves as the
metadata file for the project, holding various information like the project's
dependencies, scripts, version, and more. This file is essential for managing the
project's settings and dependencies efficiently.
Key Components of package.json:
1. Basic Metadata:
name: The name of your project.
version: The current version of your project.
description: A brief description of what your project does.
main: The entry point of your project (e.g., index.js).
2. Scripts:
The scripts section allows you to define various commands that can be run using
npm run <script-name>.
"scripts": {
"start": "node index.js",
"test": "mocha"
}
3. Dependencies
Lists the packages required for your project to run.
"dependencies": {
"express": "^4.17.1",
"mongoose": "^5.10.0"
}
4. DevDependencies:
Lists the packages needed only for development and testing.
"devDependencies": {
"nodemon": "^2.0.4",
"chai": "^4.2.0"
}
5. Engines:
Specifies the versions of Node.js and NPM that your project is compatible with.
"engines": {
"node": ">=14.0.0",
"npm": ">=6.0.0"
}
6. License:
Specifies the license under which your project is distributed.
© Edunet Foundation. All rights reserved. | 291
"license": "MIT"
7. Keywords:
An array of keywords that describe your project.
"keywords": [
"node",
"express",
"api"
]
Advantages of package.json
Dependency Management: Automates the management of project
dependencies, ensuring all required packages are installed with the correct
versions.
Script Management: Simplifies the execution of repetitive tasks through
custom scripts, enhancing productivity.
Project Metadata: Provides essential information about the project, making it
easier to understand and manage.
Version Control: Helps in maintaining version control of dependencies,
reducing the risk of breaking changes when packages are updated.
Compatibility: specifies compatible versions of Node.js and NPM, preventing
issues caused by version mismatches.
Disadvantages of package.json
Complexity: Managing a large number of dependencies can become complex
and may lead to version conflicts.
Overhead: Requires careful maintenance to ensure dependencies are up-to-
date and compatible, which can be time-consuming.
Security Risks: Dependencies might have vulnerabilities, and maintaining
secure and updated packages is crucial.
Features of package.json
Scripts: Define custom commands to streamline development tasks, testing,
and deployment.
Dependency Management: Automatically handles the installation and
versioning of dependencies.
Configuration: Centralized configuration for the project, simplifying setup and
maintenance.
Project Information: Holds metadata such as name, version, author, and
license, aiding in project documentation and management.
Custom Fields: Allow the inclusion of custom fields to store additional project-
specific information.
© Edunet Foundation. All rights reserved. | 292
Conclusions:
The package.json file is an indispensable part of a Node.js project, serving as the
backbone for dependency management, script execution, and project metadata. Its
well-structured format helps in maintaining consistency and efficiency throughout the
project lifecycle. Despite some complexities and potential security risks, the
advantages it offers in terms of automation, management, and configuration make it a
vital tool for Node.js developers.
By understanding and utilizing the features of package.json, developers can
significantly enhance the productivity and maintainability of their projects, ensuring a
smooth and organized development process.
© Edunet Foundation. All rights reserved. | 293
6.4 Working with NPM Scripts in Node.js
NPM scripts are a powerful feature of Node Package Manager (NPM) that allows
developers to automate various tasks such as building, testing, and deploying
applications. By defining scripts in the package.json file, you can streamline your
development workflow and ensure consistency across different environments.
Defining NPM Scripts
NPM scripts are defined in the scripts section of the package.json file. Each script is a
key-value pair, where the key is the name of the script and the value is the command
to be executed.
Example package.json with Scripts
{
"name": "my-nodejs-app",
"version": "1.0.0",
"description": "A simple Node.js application",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "mocha",
"build": "webpack --config webpack.config.js",
"lint": "eslint .",
"dev": "nodemon index.js",
"clean": "rm -rf dist"
},
"dependencies": {
"express": "^4.17.1"
},
"devDependencies": {
"mocha": "^8.2.1",
"eslint": "^7.12.1",
"nodemon": "^2.0.6",
"webpack": "^5.4.0",
"webpack-cli": "^4.2.0"
}
}
© Edunet Foundation. All rights reserved. | 294
Running NPM Scripts
To run an NPM script, use the npm run <script-name> command in your terminal.
Example Commands
npm run start
npm run test
npm run build
npm run lint
npm run dev
npm run clean
Some predefined script names like start and test can be run without the run
keyword:
npm start
npm test
Common Use Cases for NPM Scripts
1. Starting the Application:
The start script typically runs the main entry point of the application.
"start": "node index.js"
2. Running Tests:
The test script is used to run the test suite.
"test": "mocha"
3. Building the Project:
The build script compiles the source code.
"build": "webpack --config webpack.config.js"
4. Linting the Code:
The lint script checks the code for style and syntax issues.
"lint": "eslint ."
5. Running Development Server:
The dev script runs a development server with automatic restarts on file changes.
"dev": "nodemon index.js"
6. Cleaning Build Artifacts:
The clean script removes generated files or directories.
"clean": "rm -rf dist"
© Edunet Foundation. All rights reserved. | 295
Combining Scripts:
You can combine multiple commands in a single script using the && operator. This
allows you to run several commands sequentially.
Example Combined Script
"scripts": {
"build": "webpack --config webpack.config.js",
"test": "mocha",
"predeploy": "npm run lint && npm run test && npm run build"
}
In this example, the predeploy script will first run the lint script, then the test script, and
finally the build script.
Using Environment Variables
NPM scripts can use environment variables to configure behavior dynamically.
Environment variables can be set inline or through external configuration files.
Setting Environment Variables Inline
"scripts": {
"start": "NODE_ENV=production node index.js",
"dev": "NODE_ENV=development nodemon index.js"
}
Conclusion
NPM scripts are an invaluable tool for automating and streamlining your development
workflow in Node.js projects. By defining and using scripts, you can handle tasks such
as starting your application, running tests, building your project, and more, all with
simple commands. This not only enhances productivity but also ensures consistency
and reduces the risk of human error. Leveraging NPM scripts effectively can
significantly improve the development and deployment processes of your Node.js
applications.
© Edunet Foundation. All rights reserved. | 296
6.5 Modules in Node.js (Built-in, NPM, User defined)
Modules in Node.js are a fundamental aspect of its ecosystem, allowing developers to
structure and manage their code efficiently. There are three main types of modules in
Node.js:
1. Built-in Modules
2. NPM Modules (Third-party)
3. User-defined Modules
1. Built-in Modules:
Introduction:
Built-in modules are provided by Node.js out of the box. They are part of the Node.js
core and do not need to be installed separately. Examples include fs (file system), http
(HTTP server), path (file paths), and many others.
Features:
No Installation Required: Pre-installed with Node.js.
High Performance: Optimized for performance and stability.
Security: Maintained and updated by the Node.js core team.
Standardized API: Consistent and well-documented APIs.
Syntax and Example:
Syntax:
const module = require('moduleName');
Examples:
1. File System (fs) Module
Reading a File:
const fs = require('fs');
fs.readFile('example.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
Writing to a File:
const fs = require('fs');
fs.writeFile('example.txt', 'Hello, world!', (err) => {
if (err) throw err;
console.log('File has been saved!');
});
3. Path Module
© Edunet Foundation. All rights reserved. | 297
Working with File Paths:
const path = require('path');
const filePath = path.join('/users', 'john', 'docs', 'file.txt');
console.log(filePath); // Output: '/users/john/docs/file.txt'
Advantages:
Reliability: Being part of the Node.js core ensures that they are well-tested and
stable.
Performance: Directly integrated into the Node.js runtime.
Security: Regularly updated to patch vulnerabilities.
Disadvantages:
Limited Scope: Only cover fundamental functionalities.
Dependency: Tied to the version of Node.js being used.
Real-time Scenarios:
File operations with the fs module.
Creating HTTP servers using the http module.
Handling file paths with the path module.
2. NPM Modules (Third-party)
Introduction:
NPM (Node Package Manager) is the default package manager for Node.js. It allows
developers to install, share, and manage third-party libraries and tools. NPM hosts
thousands of packages that can be easily integrated into Node.js projects.
Syntax and Example
Syntax:
const module = require('moduleName');
Note: You need to install the module first using NPM.
npm install moduleName
Examples:
1. Express.js
Setting up a Simple Express Server:
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello, World!');
});
© Edunet Foundation. All rights reserved. | 298
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
2. Mongoose
Connecting to MongoDB and Defining a Schema:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test', {useNewUrlParser: true,
useUnifiedTopology: true});
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
console.log('Connected to MongoDB');
});
const schema = new mongoose.Schema({
name: String
});
const Cat = mongoose.model('Cat', schema);
const kitty = new Cat({ name: 'Zildjian' });
kitty.save().then(() => console.log('meow'));
3. Lodash
Using Lodash for Array Manipulation:
const _ = require('lodash');
const numbers = [1, 2, 3, 4, 5, 6];
const evens = _.filter(numbers, n => n % 2 === 0);
console.log(evens); // Output: [2, 4, 6]
© Edunet Foundation. All rights reserved. | 299
Features:
Extensive Library: Over a million packages available.
Community Support: Active community contributing to package development.
Ease of Use: Simple commands to install and manage packages.
Version Management: Handles different versions of packages.
Advantages:
Rapid Development: Reuse existing solutions to speed up development.
Diverse Functionality: Packages available for virtually any requirement.
Community Support: Large, active community providing updates and support.
Disadvantages:
Quality Variance: Not all packages are maintained or well-documented.
Dependency Management: Can lead to dependency hell if not managed
properly.
Security Risks: Potential for malicious or vulnerable packages.
Real-time Scenarios:
Web frameworks like Express.js for building web applications.
Database clients like Mongoose for MongoDB.
Utility libraries like Lodash for data manipulation.
3. User-defined Modules:
Introduction:
User-defined modules are custom modules created by developers for specific needs
within their applications. They allow for modular code organization and reusability.
Features:
Custom Functionality: Tailored to specific application requirements.
Encapsulation: Keeps related code together, improving maintainability.
Reusability: Can be reused across different parts of an application.
Syntax and Example
Syntax for Creating a Module:
// In a file named myModule.js
module.exports = {
myFunction: function() {
console.log('Hello from myFunction!');
}
};
Syntax for Using a Module:
// In another file
const myModule = require('./myModule');
myModule.myFunction();
© Edunet Foundation. All rights reserved. | 300
Examples:
1. Business Logic Module
Creating a Business Logic Module:
// In a file named businessLogic.js
module.exports = {
calculateTotal: function(price, quantity) {
return price * quantity;
}
};
Using the Business Logic Module:
const businessLogic = require('./businessLogic');
const total = businessLogic.calculateTotal(50, 3);
console.log(total); // Output: 150
2. Utility Module
Creating a Utility Module:
// In a file named utils.js
module.exports = {
greet: function(name) {
return `Hello, ${name}!`;
}
};
Using the Utility Module:
const utils = require('./utils');
console.log(utils.greet('Alice')); // Output: Hello, Alice!
3. Configuration Module
Creating a Configuration Module:
// In a file named config.js
module.exports = {
db: {
host: 'localhost',
port: 27017
},
© Edunet Foundation. All rights reserved. | 301
server: {
port: 3000
}
};
Using the Configuration Module:
const config = require('./config');
console.log(`Server running on port ${config.server.port}`);
Advantages:
Flexibility: Designed to meet specific needs of the project.
Encapsulation: Encapsulates logic and keeps the codebase clean.
Reusability: Promotes code reuse within the project.
Disadvantages
Development Time: Requires time and effort to develop.
Maintenance: Needs to be maintained by the developer.
Testing: Responsibility of the developer to test thoroughly.
Real-time Scenarios:
Business logic modules to handle specific application logic.
Utility modules for common functions like data validation.
Configuration modules to manage application configuration settings.
Why We Use Node.js Modules:
Modularity: Break down code into manageable pieces.
Reusability: Reuse code across different parts of the application or projects.
Maintenance: Easier to maintain and update.
Collaboration: Facilitates team collaboration by separating concerns.
Conclusion:
Modules in Node.js, whether built-in, from NPM, or user-defined, are essential for
creating robust, maintainable, and efficient applications. They provide a modular
structure, enable code reuse, and facilitate collaboration. Built-in modules offer core
functionalities, NPM modules extend capabilities with a vast library of third-party
packages, and user-defined modules allow for custom solutions tailored to specific
project needs. Understanding and utilizing these modules effectively can significantly
enhance the development process and result in higher quality software.
© Edunet Foundation. All rights reserved. | 302
Chapter 7: Advance Guide to Backend with
Express.js
Learning Outcomes:
Setting up an Express.js application.
Understanding middleware.
Creating routes and handling requests.
Creating RESTful routes
Handling CRUD operations
Structuring large applications.
Using middleware for logging, security, etc.
Implementing file uploads and real-time features with WebSocket.
Introduction of Express.js:
Express.js is a minimal and flexible Node.js web application framework that provides
a robust set of features to build single-page, multi-page, and hybrid web applications.
It is designed to make the development of web applications and APIs straightforward,
efficient, and robust. Express.js is widely used in the Node.js ecosystem for building
server-side applications.
Figure 87. Express Rest API
Image Source: https://www.coreycleary.me/project-structure-for-an-express-rest-api-when-
there-is-no-standard-way
© Edunet Foundation. All rights reserved. | 303
Advantages of Express.js:
Figure 88. Express Rest API
1. Simplicity and Ease of Use:
Simple to set up and get started with.
Minimalistic and unopinionated, providing only the essential features.
2. Middleware Support:
Extensive support for middleware functions, allowing for easy request and
response handling.
Middleware can be used to add functionalities such as logging, authentication,
and session management.
3. Routing:
Powerful and flexible routing system to define routes for different HTTP
methods and URL paths.
4. Scalability:
Modular structure makes it easy to scale applications by breaking them into
smaller, manageable components.
5. Community and Ecosystem:
Large and active community, with a vast ecosystem of third-party plugins and
middleware.
Disadvantages of Express.js:
1. Learning Curve:
Though simple, it might have a learning curve for developers new to Node.js
and asynchronous programming.
2. Middleware Overhead:
Extensive use of middleware can sometimes lead to performance overhead.
© Edunet Foundation. All rights reserved. | 304
3. Minimalism:
Being unopinionated means it does not provide out-of-the-box solutions for
many common tasks, requiring developers to choose and integrate additional
tools and libraries.
Features of Express.js:
1. Middleware:
Built-in and third-party middleware support for handling requests, responses,
and other tasks.
2. Routing:
Flexible and powerful routing mechanism to handle different HTTP methods
and URL patterns.
3. Template Engines:
Support for various template engines like Pug, EJS, and Handlebars, allowing
for dynamic content rendering.
4. HTTP Utilities:
Utility methods to handle common tasks such as redirection, caching, and
content negotiation.
5. Static Files:
Easy serving of static files and resources.
When to Use Express.js:
API Development:
Ideal for building RESTful APIs due to its simplicity and flexibility.
Web Applications:
Suitable for single-page, multi-page, and hybrid web applications.
Prototyping:
Great for quickly prototyping web applications and services.
Microservices:
Fits well in a microservices architecture where each service can be a small
Express.js application.
Applications We Can Create Using Express.js
RESTful APIs:
Building RESTful services and APIs for different clients (web, mobile, etc.).
Web Applications:
Creating dynamic websites with server-side rendering.
Single Page Applications (SPAs):
© Edunet Foundation. All rights reserved. | 305
Serving SPAs where the client-side code is handled by frameworks like React
or Angular.
Microservices:
Developing microservices as part of a larger distributed system.
Real-time Applications:
Combining with libraries like Socket.io to build real-time applications such as
chat apps.
7.1 Setting up an Express.js application :
Step 1: Install Node.js
Ensure that Node.js and NPM (Node Package Manager) are installed on your
machine. You can download and install Node.js from https://nodejs.org/en
Step 2: Create a Project Directory
Create a new directory for your Express.js application and navigate into it:
mkdir my-express-app
cd my-express-app
Step 3: Initialize a New Node.js Project
Initialize a new Node.js project using NPM. This command will create a package.json
file in your project directory:
npm init -y
Step 4: Install Express.js
Install Express.js as a dependency:
npm install express –save
Step 5: Create the Entry Point File
Create a file named app.js in your project directory. This file will be the entry point of
your application.
Step 6: Set Up a Basic Express Server
Open app.js in a text editor and set up a basic Express server:
const express = require('express');
const app = express();
const port = 3000;
app.get('/', (req, res) => {
res.send('Hello, World!');
© Edunet Foundation. All rights reserved. | 306
});
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
Step 7: Run the Application
Start your Express.js application by running the following command in your terminal:
node app.js
Output:
Adding More Functionality:
Once you have the basic server set up, you can add more functionality. Here are some
examples:
Serving Static Files:
Create a directory named public in your project directory and add a file named
index.html inside it:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Express Static Example</title>
</head>
<body>
<h1>Hello from Express!</h1>
</body>
</html>
Modify app.js to serve static files:
const express = require('express');
const app = express();
© Edunet Foundation. All rights reserved. | 307
const port = 3000;
app.use(express.static('public'));
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
Now, if you navigate to http://localhost:3000 in your browser, you should see the
content of index.html.
Output:
7.2 Understanding middleware
Middleware in Express.js refers to functions that execute during the lifecycle of a
request to the server. Each middleware function has access to the request object (req),
the response object (res), and the next middleware function in the application’s
request-response cycle. Middleware functions can perform various tasks, including
executing code, modifying the request and response objects, ending the request-
response cycle, and calling the next middleware function.
Key Concepts of Middleware:
1. Execution Order:
Middleware is executed sequentially in the order it is defined in the code.
2. Types of Middleware:
Figure 89. Types of Middleware
© Edunet Foundation. All rights reserved. | 308
Application-level middleware: Bound to an instance of the express object.
Router-level middleware: Bound to an instance of express.Router().
Error-handling middleware: Takes four arguments (err, req, res, next).
Built-in middleware: Provided by Express.js (e.g., express.json()).
Third-party middleware: Provided by the community (e.g., body-parser,
morgan).
Defining and Using Middleware
1. Application-level Middleware
Application-level middleware is bound to an instance of the express object using
app.use() or app.METHOD().
const express = require('express');
const app = express();
const port = 3000;
// Application-level middleware
app.use((req, res, next) => {
console.log('Time:', Date.now());
next();
});
app.get('/', (req, res) => {
res.send('Hello, World!');
});
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
Output:
© Edunet Foundation. All rights reserved. | 309
Explanation:
Importing Express:
const express = require('express');
This line imports the Express module. Express is a minimal and flexible Node.js web
application framework that provides a robust set of features to develop web and mobile
applications.
Creating an Express Application:
const app = express();
This line creates an instance of an Express application. The app variable is used to
set up the server and define the routes.
Setting the Port:
const port = 3000;
This line defines the port number on which the server will listen for incoming requests.
In this case, it is set to 3000.
Application-level Middleware:
app.use((req, res, next) => {...});
This line defines application-level middleware using app.use(). Middleware
functions are functions that have access to the request object (req), the
response object (res), and the next middleware function in the application’s
request-response cycle.
req: The request object, representing the HTTP request.
res: The response object, representing the HTTP response that the Express
app sends when it receives an HTTP request.
next: A function that, when called, executes the next middleware function in the
stack.
console.log('Time:', Date.now());
This line logs the current timestamp to the console each time a request is
received by the server. Date.now() returns the number of milliseconds elapsed
since January 1, 1970 00:00:00 UTC.
next();
© Edunet Foundation. All rights reserved. | 310
This line calls the next middleware function in the stack. If this function is not
called, the request will be left hanging and will not proceed to the next
middleware or route handler.
Route Handler:
app.get('/', (req, res) => {...});
This line defines a route handler for GET requests to the root URL (/). The
app.get() method is used to define routes that should respond to GET requests.
(req, res) => {...}
This is the callback function that handles the incoming request and sends a
response. It takes two parameters:
req: The request object.
res: The response object.
res.send('Hello, World!');
This line sends the response 'Hello, World!' back to the client. The res.send()
method is used to send a response back to the client.
Starting the Server:
app.listen(port, () => {...});
This line starts the Express server and makes it listen on the specified port
(3000).
The app.listen() method takes two arguments:
port: The port number on which the server should listen.
A callback function that is executed once the server starts listening.
console.log(Server is running on http://localhost:${port}`);`
This line logs a message to the console indicating that the server is running and
listening on the specified port. It uses template literals (backticks) to insert the
port number into the string.
2. Router-level Middleware
Router-level middleware works in the same way as application-level middleware,
except it is bound to an instance of express.Router().
Example:
const express = require('express');
const app = express();
const router = express.Router();
const port = 3000;
// Router-level middleware
router.use((req, res, next) => {
console.log('Request URL:', req.originalUrl);
next();
});
router.get('/', (req, res) => {
res.send('Hello from Router!');
© Edunet Foundation. All rights reserved. | 311
});
app.use('/router', router);
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
Output:
Explanation:
Importing Express:
const express = require('express');
This line imports the Express module. Express is a minimal and flexible Node.js web
application framework that provides a robust set of features to develop web and mobile
applications.
Creating an Express Application:
const app = express();
This line creates an instance of an Express application. The app variable is used to
set up the server and define the routes.
Creating a Router:
const router = express.Router();
This line creates an instance of an Express router. A router is a mini-application that
can handle its own set of routes and middleware. It is useful for organizing routes and
middleware logically, especially in large applications.
© Edunet Foundation. All rights reserved. | 312
Setting the Port:
const port = 3000;
This line defines the port number on which the server will listen for incoming requests.
In this case, it is set to 3000.
Router-level Middleware:
router.use((req, res, next) => {...});
This line defines middleware specific to the router using router.use(). Middleware
functions are functions that have access to the request object (req), the response
object (res), and the next middleware function in the application’s request-response
cycle.
console.log('Request URL:', req.originalUrl);
This line logs the URL of each incoming request to the console. req.originalUrl
contains the original request URL.
next();
This line calls the next middleware function in the stack. If this function is not called,
the request will be left hanging and will not proceed to the next middleware or route
handler.
Router Route Handler:
router.get('/', (req, res) => {...});
This line defines a route handler for GET requests to the root URL (/) of the router.
The router.get() method is used to define routes that should respond to GET requests.
(req, res) => {...}
This is the callback function that handles the incoming request and sends a response.
It takes two parameters:
req: The request object.
res: The response object.
res.send('Hello from Router!');
This line sends the response 'Hello from Router!' back to the client. The res.send()
method is used to send a response back to the client.
Using the Router in the App:
app.use('/router', router);
© Edunet Foundation. All rights reserved. | 313
This line mounts the router on the /router path. This means that any requests to URLs
that start with /router will be handled by the routes and middleware defined in the router
object. For example, a request to /router will be handled by the route defined in
router.get('/').
Starting the Server:
app.listen(port, () => {...});
This line starts the Express server and makes it listen on the specified port (3000).
The app.listen() method takes two arguments:
port: The port number on which the server should listen.
A callback function that is executed once the server starts listening.
console.log(Server is running on http://localhost:${port}`);`
This line logs a message to the console indicating that the server is running and
listening on the specified port. It uses template literals (backticks) to insert the port
number into the string.
3. Built-in Middleware:
Express.js comes with a few built-in middleware functions, such as express.json(),
express.urlencoded(), and express.static().
const express = require('express');
const app = express();
const port = 3000;
// Built-in middleware for parsing JSON bodies
app.use(express.json());
app.post('/data', (req, res) => {
res.json({ message: 'Data received!', data: req.body });
});
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
Output:
© Edunet Foundation. All rights reserved. | 314
Explanation:
Built-in Middleware for Parsing JSON Bodies:
app.use(express.json());
This line adds a piece of built-in middleware to the Express application. The
express.json() middleware function parses incoming requests with JSON payloads
and is based on body-parser. When this middleware is in place, it makes it easier to
handle JSON data sent in the body of HTTP requests (such as those from POST
requests).
Route Handler for POST Requests:
app.post('/data', (req, res) => {...});
This line defines a route handler for POST requests to the /data endpoint. The
app.post() method is used to define routes that should respond to POST requests.
(req, res) => {...}
© Edunet Foundation. All rights reserved. | 315
This is the callback function that handles the incoming request and sends a response.
It takes two parameters:
req: The request object, representing the HTTP request.
res: The response object, representing the HTTP response that the Express app
sends when it receives an HTTP request.
res.json({ message: 'Data received!', data: req.body });
This line sends a JSON response back to the client. The res.json() method converts a
JavaScript object or array into a JSON string and sends it in the response. The object
being sent contains two properties:
message: A string indicating that the data was received.
data: The body of the incoming request, accessible via req.body because of the
express.json() middleware.
Starting the Server:
app.listen(port, () => {...});
This line starts the Express server and makes it listen on the specified port (3000).
The app.listen() method takes two arguments:
port: The port number on which the server should listen.
A callback function that is executed once the server starts listening.
console.log(Server is running on http://localhost:${port}`);`
This line logs a message to the console indicating that the server is running and
listening on the specified port. It uses template literals (backticks) to insert the port
number into the string.
4. Error-handling Middleware:
Error-handling middleware functions take four arguments: (err, req, res, next). These
functions are defined after all other app.use() and routes calls.
const express = require('express');
const app = express();
const port = 3000;
// Error-handling middleware
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
app.get('/', (req, res) => {
© Edunet Foundation. All rights reserved. | 316
throw new Error('BROKEN'); // Simulating an error
});
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
Output:
Explanation:
Error-handling Middleware:
app.use((err, req, res, next) => {...});
This line defines an error-handling middleware function. Error-handling middleware is
defined with four arguments: err, req, res, and next. It is specifically used to handle
errors that occur during the execution of the application.
console.error(err.stack);
This line logs the stack trace of the error to the console. The err.stack property contains
the stack trace of the error, which is useful for debugging purposes.
res.status(500).send('Something broke!');
This line sends a response with a status code of 500 (Internal Server Error) and the
message 'Something broke!'. The res.status() method sets the HTTP status code, and
the res.send() method sends the response to the client.
Route Handler with Simulated Error:
app.get('/', (req, res) => {...});
This line defines a route handler for GET requests to the root URL (/). The app.get()
method is used to define routes that should respond to GET requests.
throw new Error('BROKEN');
This line simulates an error by throwing a new Error object with the message
'BROKEN'. Throwing an error inside a route handler will cause the error to be caught
by the error-handling middleware defined earlier.
© Edunet Foundation. All rights reserved. | 317
Starting the Server:
app.listen(port, () => {...});
This line starts the Express server and makes it listen on the specified port (3000).
The app.listen() method takes two arguments:
port: The port number on which the server should listen.
A callback function that is executed once the server starts listening.
console.log(Server is running on http://localhost:${port}`);`
This line logs a message to the console indicating that the server is running and
listening on the specified port. It uses template literals (backticks) to insert the port
number into the string.
Third-party Middleware:
You can use middleware provided by the community, such as morgan for logging,
body-parser for parsing request bodies, and more.
const express = require('express');
const morgan = require('morgan');
const app = express();
const port = 3000;
// Third-party middleware
app.use(morgan('combined'));
app.get('/', (req, res) => {
res.send('Hello, World!');
});
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
Output:
Explanation:
© Edunet Foundation. All rights reserved. | 318
Using Third-party Middleware:
app.use(morgan('combined'));
This line adds Morgan as middleware to the Express application. The app.use()
method mounts the specified middleware function(s) at the specified path.
morgan('combined') is a pre-defined format string that logs the details of incoming
requests in the Apache combined log format, which includes information such as the
remote address, the request method, the URL, the response status, the response time,
and more. This is useful for logging HTTP requests for debugging and monitoring
purposes.
Route Handler:
app.get('/', (req, res) => {...});
This line defines a route handler for GET requests to the root URL (/). The app.get()
method is used to define routes that should respond to GET requests.
(req, res) => {...}
This is the callback function that handles the incoming request and sends a response.
It takes two parameters:
req: The request object, representing the HTTP request.
res: The response object, representing the HTTP response that the Express app
sends when it receives an HTTP request.
res.send('Hello, World!');
This line sends the response 'Hello, World!' back to the client. The res.send() method
is used to send a response back to the client.
Conclusion:
Middleware is a core concept in Express.js, allowing developers to handle requests
and responses in a modular and organized manner. By understanding how to define
and use different types of middleware, you can effectively manage the flow of your
application's request-response cycle, implement functionalities like logging,
authentication, error handling, and more.
7.3 Creating routes and handling requests
In Express.js, routing refers to how an application’s endpoints (URIs) respond to client
requests. Express is a web application framework for Node.js, designed for building
web applications and APIs. Routes define the application’s response to specific HTTP
methods and endpoints. For example, a GET request to the /about endpoint might
return information about the application, while a POST request to /submit might handle
form submissions.
© Edunet Foundation. All rights reserved. | 319
Features of Express.js
Middleware: Functions that execute during the lifecycle of a request to the
server.
Routing: Defines application endpoints and how they respond to client
requests.
Templating: Supports various template engines to dynamically render HTML
pages.
Debugging: Provides a powerful debugging mechanism.
HTTP Helpers: Simplifies the process of writing handlers for requests and
responses.
Performance: High performance due to its asynchronous, non-blocking nature.
Example: Create a simple Express.js server with routing and request handling.
Code:
// Import Express
const express = require('express');
// Create an instance of Express
const app = express();
// Define a port
const port = 3000;
// Middleware to parse JSON bodies
app.use(express.json());
// Define a simple route
app.get('/', (req, res) => {
res.send('Hello, World!');
});
// Define another route with a parameter
app.get('/user/:id', (req, res) => {
const userId = req.params.id;
res.send(`User ID: ${userId}`);
});
// Handle POST request
app.post('/user', (req, res) => {
const user = req.body;
res.send(`User created: ${JSON.stringify(user)}`);
});
// Start the server
© Edunet Foundation. All rights reserved. | 320
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
Output:
Explanation
Importing Express: const express = require('express'); - Imports the
Express module.
Creating an Instance: const app = express(); - Creates an Express
application.
Port Definition: const port = 3000; - Defines the port on which the server will
listen.
Middleware: app.use(express.json()); - Middleware to parse JSON bodies
from incoming requests.
Defining Routes:
app.get('/', (req, res) => {...}); - Handles GET requests to the root URL.
app.get('/user/:id', (req, res) => {...}); - Handles GET requests to /user/:id,
where :id is a route parameter.
app.post('/user', (req, res) => {...}); - Handles POST requests to /user.
Starting the Server: app.listen(port, () => {...}); - Starts the server and listens
on the specified port.
Running the Server:
To run the server, navigate to the directory containing app.js in your terminal and
execute the following command:
node app.js
© Edunet Foundation. All rights reserved. | 321
You should see the following output in your terminal:
Server running at http://localhost:3000
Testing the Routes:
You can test the routes using a web browser, curl command, or a tool like Postman.
1. GET /
Open your web browser and go to http://localhost:3000/.
Expected Output:
2. GET /user/:id
Replace :id with a specific user ID, e.g., http://localhost:3000/user/123.
Expected Output:
3. POST /user
Use Postman to send a POST request with a JSON body.
© Edunet Foundation. All rights reserved. | 322
This example demonstrates the basics of setting up an Express.js server, defining
routes, and handling GET and POST requests.
Advantages
Simplicity and Flexibility: Defining routes in Express.js is straightforward and
allows for a great deal of flexibility in how requests are handled.
Middleware Integration: Routes can be easily extended with middleware to
handle tasks such as authentication, logging, and data validation.
Scalability: Routes can be modularized and organized efficiently, making it
easier to manage larger applications.
Support for Multiple HTTP Methods: Express allows handling various HTTP
methods (GET, POST, PUT, DELETE, etc.) for the same endpoint.
Disadvantages
Callback Hell: If not managed properly, nested callbacks in route handlers can
become difficult to manage.
Overhead for Simple Applications: For very simple applications, the added
complexity of setting up routes and middleware might be unnecessary.
Middleware Mismanagement: Incorrect order or mismanagement of
middleware can lead to unexpected behavior and security issues.
Conclusion:
© Edunet Foundation. All rights reserved. | 323
Express.js is a powerful, flexible, and minimalistic web framework for Node.js, ideal
for building both small-scale and large-scale web applications. Its middleware-based
architecture allows for easy extensibility, while its strong community and ecosystem
support enhance its capabilities. Understanding the basics of routing, middleware, and
request handling in Express.js can significantly boost your efficiency in developing
server-side applications.
7.4 Principles of REST architecture
REST (Representational State Transfer) is an architectural style for designing
networked applications. It relies on a stateless, client-server, cacheable
communications protocol -- the HTTP protocol is used most often. RESTful
applications use HTTP requests to perform CRUD (Create, Read, Update, Delete)
operations.
Express.js is a minimal and flexible Node.js web application framework that provides
a robust set of features for web and mobile applications. It allows you to create a
server-side application and RESTful APIs efficiently.
Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. It allows you
to run JavaScript on the server side.
Figure 90. Principles of REST architecture
© Edunet Foundation. All rights reserved. | 324
Advantages:
Scalability:
RESTful services can be scaled easily due to their stateless nature. Each
request from a client contains all the information the server needs to fulfill that
request, allowing the server to handle more requests.
Simplicity and Uniform Interface:
REST uses standard HTTP methods (GET, POST, PUT, DELETE), which are
familiar to developers and easily understood. This uniform interface simplifies
the design and interaction with the API.
Flexibility and Portability:
REST APIs can be consumed by any client that can send HTTP requests. This
includes web browsers, mobile devices, and even other servers, making REST
APIs highly portable.
Performance:
RESTful services can improve performance through the use of caching
mechanisms. Responses can be marked as cacheable, allowing clients to
reuse them.
Language and Platform Agnostic:
REST APIs can be developed and consumed in any programming language,
providing flexibility in choosing the technology stack for both the client and
server.
Modularity and Reusability:
RESTful services encourage the development of modular and reusable
components. Each endpoint represents a discrete operation that can be tested
and used independently.
Disadvantages of REST Architecture in Express.js and Node.js
Statelessness:
While statelessness improves scalability, it can lead to overhead since each
request must contain all the necessary information. This can result in larger
payloads and increased network traffic.
Limited Security:
REST APIs typically use HTTP, which may not be secure. Implementing
security features like authentication, authorization, and encryption requires
additional effort and can be complex.
Performance Overhead:
Due to the stateless nature, repetitive data transfer between client and server
can increase bandwidth usage and reduce performance, especially in high-
latency networks.
Complexity in Error Handling:
Handling errors and providing meaningful responses in a consistent way across
different endpoints can be challenging and requires careful design.
© Edunet Foundation. All rights reserved. | 325
Lack of Transactions:
REST does not natively support transactions across multiple resource updates.
Implementing transactional behavior (like in a traditional database system) can
be complex and requires additional logic.
Features:
Routing:
Express.js provides a robust routing mechanism to define URL paths and their
corresponding handlers. This allows you to define RESTful endpoints for CRUD
operations easily.
Middleware Support:
Express.js has a powerful middleware system that allows you to define reusable
code for processing requests and responses. Middleware can be used for tasks
like authentication, logging, and data validation.
Asynchronous Handling:
Node.js is built on an event-driven, non-blocking I/O model, which makes it
highly efficient for handling multiple concurrent requests. This is particularly
beneficial for RESTful services that need to handle high loads.
JSON Support:
Express.js has built-in support for JSON, the most common data format used
in RESTful services. This simplifies data parsing and serialization.
Lightweight and Fast:
Express.js is minimal and unopinionated, providing a lightweight framework that
can be extended with middleware as needed. This results in faster performance
and reduced overhead.
Error Handling:
Express.js provides mechanisms for centralized error handling, allowing you to
define error-handling middleware that can catch and process errors
consistently across your application.
Modular Structure:
With Node.js and Express.js, you can structure your application modularly by
separating routes, controllers, models, and middleware into different files and
directories. This improves maintainability and readability.
Community and Ecosystem:
Both Node.js and Express.js have large and active communities. This means a
wealth of libraries, tools, and resources are available to help you build and
maintain RESTful services.
Here's a clear explanation of the REST architecture using Express.js and Node.js:
Components of REST Architecture:
Resources and URIs:
Resources are the fundamental components of a RESTful API. They represent entities
such as users, products, or orders.
© Edunet Foundation. All rights reserved. | 326
Each resource is identified by a URI (Uniform Resource Identifier). For example, /users
or /products.
HTTP Methods:
RESTful services typically use the following HTTP methods to perform operations on
resources:
GET: Retrieve a resource.
POST: Create a new resource.
PUT: Update an existing resource.
DELETE: Delete a resource.
PATCH: Partially update a resource.
Statelessness:
Each request from a client to the server must contain all the information the server
needs to fulfill that request. The server does not store any state about the client
session on the server side.
Client-Server Architecture:
RESTful systems adhere to a client-server architecture, where the client and server
are separate and interact through HTTP requests and responses.
Cacheability:
Responses must be defined as cacheable or non-cacheable to improve performance
and scalability.
7.4.1 Creating RESTful routes:
Creating RESTful routes involves defining endpoints in your application that
correspond to the operations you want to perform on your resources (like retrieving,
creating, updating, or deleting data). Here’s a detailed guide on how to create RESTful
routes using Express.js:
Steps to Create RESTful Routes
1. Set Up Express:
Ensure you have Node.js and Express installed.
Create a new project directory and initialize it.
mkdir myapp
cd myapp
npm init -y
npm install express
2. Create the Server:
Create an index.js file and set up the Express server
© Edunet Foundation. All rights reserved. | 327
const express = require('express');
const app = express();
const port = 3000;
app.use(express.json()); // To parse JSON bodies
// Define routes
app.get('/', (req, res) => {
res.send('Welcome to the RESTful API!');
});
// Start the server
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
3. Define RESTful Routes:
Create routes to handle CRUD operations for a resource, e.g., users
const users = [];
// Create a new user
app.post('/users', (req, res) => {
const user = req.body;
users.push(user);
res.status(201).send(user);
});
// Get all users
app.get('/users', (req, res) => {
res.send(users);
});
// Get a user by ID
app.get('/users/:id', (req, res) => {
const user = users.find(u => u.id === parseInt(req.params.id));
if (!user) return res.status(404).send('User not found');
res.send(user);
});
// Update a user by ID
app.put('/users/:id', (req, res) => {
const user = users.find(u => u.id === parseInt(req.params.id));
if (!user) return res.status(404).send('User not found');
user.name = req.body.name;
res.send(user);
© Edunet Foundation. All rights reserved. | 328
});
// Delete a user by ID
app.delete('/users/:id', (req, res) => {
const index = users.findIndex(u => u.id === parseInt(req.params.id));
if (index === -1) return res.status(404).send('User not found');
users.splice(index, 1);
res.status(204).send();
});
4. Run the Server:
Start your server by running:
node index.js
Explanation:
1. Require the Express Module:
const express = require('express');
This line imports the Express module, a popular web framework for Node.js used to
build web applications and APIs.
2. Create an Express Application:
const app = express();
This line creates an instance of an Express application.
3. Set the Port:
const port = 3000;
This line defines the port number (3000) on which the server will listen for incoming
requests.
4. Middleware to Parse JSON Bodies:
app.use(express.json());
This middleware parses incoming requests with JSON payloads. It makes the
req.body object available for use in your routes.
5. Define a Route for the Root URL:
app.get('/', (req, res) => {
res.send('Welcome to the RESTful API!');
});
© Edunet Foundation. All rights reserved. | 329
This route handler listens for GET requests to the root URL ('/'). When a request is
made to this URL, the server responds with the message "Welcome to the RESTful
API!".
6. Start the Server:
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
This line starts the server and listens on the specified port (3000). When the server
starts successfully, it logs a message to the console indicating the URL where the
server is running.
7.5 Handling CRUD operations
We'll build a simple API for managing a collection of books. This example will cover
the basic CRUD (Create, Read, Update, Delete) operations.
Step 1: Set Up Your Project
Initialize a new Node.js project:
mkdir express-rest-api
cd express-rest-api
npm init -y
Install Express.js:
npm install express
Step 2: Create the Express Server
Create a file named server.js:
// server.js
const express = require('express');
const app = express();
const port = 3000;
// Middleware to parse JSON bodies
app.use(express.json());
// In-memory database (for simplicity)
let books = [];
// Routes
app.get('/', (req, res) => {
res.send('Welcome to the Books API');
});
// Start the server
© Edunet Foundation. All rights reserved. | 330
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
Step 3: Define RESTful Routes
Create CRUD routes for the book collection:
// server.js (continued)
// Create a new book
app.post('/books', (req, res) => {
const book = req.body;
book.id = books.length + 1;
books.push(book);
res.status(201).json(book);
});
// Get all books
app.get('/books', (req, res) => {
res.json(books);
});
// Get a single book by ID
app.get('/books/:id', (req, res) => {
const bookId = parseInt(req.params.id, 10);
const book = books.find(b => b.id === bookId);
if (book) {
res.json(book);
} else {
res.status(404).json({ message: 'Book not found' });
}
});
// Update a book by ID
app.put('/books/:id', (req, res) => {
const bookId = parseInt(req.params.id, 10);
const index = books.findIndex(b => b.id === bookId);
if (index !== -1) {
books[index] = { ...books[index], ...req.body };
res.json(books[index]);
} else {
res.status(404).json({ message: 'Book not found' });
}
});
© Edunet Foundation. All rights reserved. | 331
// Delete a book by ID
app.delete('/books/:id', (req, res) => {
const bookId = parseInt(req.params.id, 10);
const index = books.findIndex(b => b.id === bookId);
if (index !== -1) {
books.splice(index, 1);
res.status(204).send();
} else {
res.status(404).json({ message: 'Book not found' });
}
});
Step 4: Test the API
Start the server:
node server.js
Use a tool like Postman or curl to test the API endpoints.
Explanation of the Code:
Express Setup:
const express = require('express'); - Import the Express library.
const app = express(); - Create an instance of an Express application.
const port = 3000; - Define the port number the server will listen on.
app.use(express.json()); - Middleware to parse JSON request bodies.
In-Memory Database:
let books = []; - Simple array to store books in memory.
Routes:
app.get('/', (req, res) => { ... }); - Define a route for the root URL.
app.post('/books', (req, res) => { ... }); - Define a route to create a new book.
app.get('/books', (req, res) => { ... }); - Define a route to get all books.
app.get('/books/:id', (req, res) => { ... }); - Define a route to get a book by ID.
app.put('/books/:id', (req, res) => { ... }); - Define a route to update a book by ID.
app.delete('/books/:id', (req, res) => { ... }); - Define a route to delete a book by
ID.
Starting the Server:
app.listen(port, () => { ... }); - Start the server and listen on the specified port.
Using Postman to Test the Express.js API
1. Create a new book:
© Edunet Foundation. All rights reserved. | 332
Start your Express.js server: Ensure your server.js file is running by executing
node server.js in your terminal.
2. Open Postman:
If you haven't already installed Postman, you can download it from here.
3. Create a POST request to add a new book:
Open Postman.
Set the request type to POST.
Enter the request URL: http://localhost:3000/books.
Go to the Body tab.
Select raw and choose JSON (application/json) from the dropdown.
In the text area below, enter JSON data for a book, e.g
{
"title": "The Great Gatsby",
"author": "F. Scott Fitzgerald"
}
Click Send. You should receive a response with the newly created book.
4. Create a GET request to fetch all books:
Change the request type to GET.
Enter the request URL: http://localhost:3000/books.
Click Send. You should see a list of all books stored in your API's memory.
5. Create a GET request to fetch a single book by ID:
Change the request type to GET.
Enter the request URL with an ID, e.g., http://localhost:3000/books/1 (replace
1 with an actual ID from a book you added earlier).
Click Send. You should receive the details of the specific book.
6. Create a PUT request to update a book by ID:
Change the request type to PUT.
Enter the request URL with an ID, e.g., http://localhost:3000/books/1 (replace
1 with the ID of the book you want to update).
Go to the Body tab.
Select raw and choose JSON (application/json) from the dropdown.
In the text area below, enter the updated JSON data for the book, e.g.,
Json
{
"title": "Updated Title"
}
Click Send. You should receive a response with the updated book details.
7. Create a DELETE request to delete a book by ID:
Change the request type to DELETE.
© Edunet Foundation. All rights reserved. | 333
Enter the request URL with an ID, e.g., http://localhost:3000/books/1 (replace
1 with the ID of the book you want to delete).
Click Send. You should receive a successful response with status 204 No
Content.
Output:
POST:
GET:
PUT:
© Edunet Foundation. All rights reserved. | 334
DELETE:
7.6 Error handling and validation
Proper error handling and validation are crucial for maintaining the reliability and
security of large-scale Express.js applications. Below is an example explanation and
structure for implementing error handling and validation:
1. Error Handling in Express.js:
Error handling in Express.js involves middleware functions that capture errors and
handle them gracefully to prevent crashes and provide meaningful responses to
clients.
Example Explanation:
In an Express.js application, errors can occur during request processing, database
operations, or other asynchronous tasks. Middleware functions like next(err) pass
errors to the Express error handler (app.use((err, req, res, next) => {...})), where they
can be logged and responded to appropriately.
Structure:
// Example of Express.js error handling middleware
© Edunet Foundation. All rights reserved. | 335
const express = require('express');
const app = express();
// Middleware to handle JSON parsing errors
app.use(express.json());
// Example route with intentional error
app.get('/example', (req, res, next) => {
// Simulating an error (e.g., database operation failure)
const err = new Error('Database operation failed');
err.status = 500;
next(err);
});
// Error handling middleware
app.use((err, req, res, next) => {
// Logging the error
console.error('Error occurred:', err);
// Sending an appropriate error response to the client
res.status(err.status || 500).json({
error: {
message: err.message || 'Internal Server Error'
}
});
});
// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Explanation of Output:
Middleware Setup: The express.json() middleware handles JSON parsing
errors by automatically responding with a 400 status code and error message
if the JSON is invalid.
Route Error: When accessing /example, an intentional error (Database
operation failed) is thrown. This error is passed to the error handling
middleware.
Error Handling Middleware: Logs the error to the console and sends an
appropriate JSON response to the client with the error message and status
code (500 in this case).
© Edunet Foundation. All rights reserved. | 336
2. Validation in Express.js:
Validation in Express.js ensures that incoming data meets specified criteria before
processing it further. This prevents invalid data from entering the application and
enhances security and data integrity.
Example Explanation:
Middleware functions and libraries like express-validator simplify validation by
providing methods to check request bodies, query parameters, and route parameters
against predefined rules.
Structure:
// Example of validation using express-validator middleware
const express = require('express');
const { body, validationResult } = require('express-validator');
const app = express();
// Middleware to parse JSON
app.use(express.json());
// Validation middleware for POST /user route
app.post('/user',
// Validation rules using express-validator
body('username').isLength({ min: 3 }).withMessage('Username must be at least
3 characters long'),
body('email').isEmail().withMessage('Please enter a valid email address'),
// Custom error handler for validation errors
(req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
// Process valid data
// For example, save user to database
res.status(201).json({ message: 'User created successfully' });
}
);
// Error handling middleware
app.use((err, req, res, next) => {
console.error('Error occurred:', err);
© Edunet Foundation. All rights reserved. | 337
res.status(500).json({ error: { message: 'Internal Server Error' } });
});
// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Explanation of Output:
Validation Middleware: Validates username and email fields using express-
validator rules (isLength, isEmail). If validation fails, it returns a 400 status code
with an array of validation errors.
Custom Error Handling: Custom error handling middleware (app.use) catches
and logs any errors that occur during request processing, ensuring consistent
error responses.
Conclusion:
Implementing robust error handling and validation in Express.js is essential for building
scalable and secure web applications. Middleware functions and libraries like express-
validator simplify validation logic, while custom error handling middleware ensures
errors are handled gracefully, providing clear feedback to clients. This approach
enhances application reliability, security, and user experience.
7.7 Using middleware for logging, and security:
7.7.1 Logging Middleware:
Logging middleware records important information about requests, responses, errors,
and other events in the application. It helps in monitoring and debugging applications
effectively.
Example Structure:
const express = require('express');
const morgan = require('morgan');
const app = express();
// Middleware to log requests
app.use(morgan('dev'));
// Middleware to parse JSON requests
app.use(express.json());
© Edunet Foundation. All rights reserved. | 338
// Example route with intentional error
app.get('/example', (req, res, next) => {
// Simulating an error (e.g., database operation failure)
const err = new Error('Database operation failed');
err.status = 500;
next(err);
});
// Error handling middleware
app.use((err, req, res, next) => {
// Logging the error
console.error('Error occurred:', err);
// Sending an appropriate error response to the client
res.status(err.status || 500).json({
error: {
message: err.message || 'Internal Server Error'
}
});
});
// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
This is a basic Express.js application that demonstrates middleware usage for logging
requests with `morgan`, parsing JSON requests with `express.json()`, handling errors,
and starting a server on a specified port.
Here's a breakdown of what each part does:
1. Express and Morgan Setup:
`const express = require('express');`: Imports the Express.js framework.
`const morgan = require('morgan');`: Imports the Morgan middleware for
logging HTTP requests.
`const app = express();`: Creates an instance of the Express application.
2. Middleware Setup:
`app.use(morgan('dev'));`: Configures Morgan to log HTTP requests with the
'dev' format, which provides concise logging including HTTP method, URL,
status code, response time, and size.
`app.use(express.json());`: Middleware to parse incoming JSON requests. It
allows the application to handle JSON-encoded request bodies.
© Edunet Foundation. All rights reserved. | 339
3. Example Route with Error Handling:
`app.get('/example', (req, res, next) => { ... });`: Defines a route for `/example`
that intentionally throws an error (`Database operation failed`). This simulates
a scenario where a database operation fails.
`next(err);`: Passes the error (`err`) to the error handling middleware
(`app.use((err, req, res, next) => { ... });`).
4. Error Handling Middleware:
`app.use((err, req, res, next) => { ... });`: Error handling middleware that catches
any errors thrown by routes or middleware.
`console.error('Error occurred:', err);`: Logs the error details to the console for
debugging purposes.
`res.status(err.status || 500).json({ error: { message: err.message || 'Internal
Server Error' } });`: Sends an appropriate JSON response to the client with the
error status code and message.
5. Server Initialization:
`const PORT = process.env.PORT || 3000;`: Specifies the port number from the
environment variable `PORT` or defaults to `3000`.
`app.listen(PORT, () => { ... });`: Starts the Express server, listening on the
specified port (`PORT`). Logs a message to the console once the server is
running.
Usage:
To run this Express.js application:
Ensure Node.js and npm (Node Package Manager) are installed on your
system.
Save the code into a file (e.g., `app.js`).
Open a terminal or command prompt and navigate to the directory containing
`app.js`.
Install Express and Morgan if not already installed (`npm install express
morgan`).
Start the application by running `node app.js`.
Upon starting, you can access the server at `http://localhost:3000/example` to trigger
the intentional error and observe the error handling in action, including logging and
JSON response.
This setup provides a foundational structure for handling HTTP requests, parsing
JSON data, logging requests for debugging purposes, and handling errors gracefully
in an Express.js application.
7.7.2 Security Middleware:
© Edunet Foundation. All rights reserved. | 340
Security middleware in Express.js enhances application security by implementing
measures such as HTTP headers, CSRF protection, and sanitization to mitigate
common web vulnerabilities.
Structure:
const express = require('express');
const helmet = require('helmet');
const csrf = require('csurf');
const app = express();
// Middleware for setting HTTP headers for security
app.use(helmet());
// Middleware to parse JSON requests
app.use(express.json());
// CSRF protection middleware
app.use(csrf({ cookie: true }));
// Example route with intentional CSRF vulnerability
app.post('/submit', (req, res, next) => {
// Simulate processing form data
res.json({ message: 'Form data submitted successfully' });
});
// Error handling middleware
app.use((err, req, res, next) => {
console.error('Error occurred:', err);
res.status(500).json({ error: { message: 'Internal Server Error' } });
});
// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Output:
© Edunet Foundation. All rights reserved. | 341
Explanation:
This Express.js application includes middleware for enhancing security by setting
HTTP headers with helmet, parsing JSON requests with express.json(), and
implementing CSRF protection with csurf. Below is an explanation of each middleware
component and its role in improving application security:
Express.js Application with Security Middleware
1. Helmet Middleware:
// Middleware for setting HTTP headers for security
app.use(helmet());
Purpose: Helmet helps secure Express.js applications by setting various HTTP
headers to protect against common vulnerabilities such as Cross-Site Scripting (XSS),
Clickjacking, and MIME Sniffing.
2. Express.json Middleware:
// Middleware to parse JSON requests
app.use(express.json());
Purpose: express.json() parses incoming JSON requests, enabling the application to
handle JSON-encoded request bodies. This middleware is essential for processing
data sent via APIs or forms with JSON payloads.
3. CSRF Protection Middleware (csurf):
// CSRF protection middleware
app.use(csrf({ cookie: true }));
Purpose: csurf middleware provides Cross-Site Request Forgery (CSRF) protection
by generating and verifying CSRF tokens. It helps prevent malicious attacks where
unauthorized commands are transmitted from a user that the website trusts.
4. Example Route with Intentional CSRF Vulnerability:
// Example route with intentional CSRF vulnerability
app.post('/submit', (req, res, next) => {
© Edunet Foundation. All rights reserved. | 342
// Simulate processing form data
res.json({ message: 'Form data submitted successfully' });
});
Purpose: This route (/submit) simulates processing form data without verifying CSRF
tokens. It illustrates a vulnerability that csurf middleware protects against by ensuring
CSRF tokens are included in requests.
5. Error Handling Middleware:
// Error handling middleware
app.use((err, req, res, next) => {
console.error('Error occurred:', err);
res.status(500).json({ error: { message: 'Internal Server Error' } });
});
Purpose: The error handling middleware (app.use) catches and logs any errors that
occur during request processing. It ensures that if an unexpected error happens, the
server responds with a generic error message (Internal Server Error) and a 500 status
code.
6. Server Initialization:
// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Purpose: Starts the Express server on the specified port (PORT). If the PORT
environment variable is not set, it defaults to port 3000. Logs a message to the console
once the server is running.
Usage:
To run this Express.js application:
Ensure Node.js and npm (Node Package Manager) are installed on your
system.
Save the code into a file (e.g., app.js).
Open a terminal or command prompt and navigate to the directory containing
app.js.
Install Express, Helmet, and csurf if not already installed (npm install express
helmet csurf).
Start the application by running node app.js.
Upon starting, the server is accessible at http://localhost:3000/submit. Accessing this
route without including a CSRF token (when using csurf middleware) would typically
result in an error, demonstrating the middleware's protective role against CSRF
attacks.
© Edunet Foundation. All rights reserved. | 343
This setup provides a foundational structure for enhancing security in an Express.js
application by implementing HTTP headers with Helmet, parsing JSON requests,
protecting against CSRF attacks with csurf middleware, and handling errors gracefully.
7.8 Implementing file uploads and real-time features with
WebSocket
Implementing file uploads and real-time features with WebSocket in an Express.js
application involves integrating two distinct functionalities: handling file uploads via
HTTP and enabling real-time communication using WebSocket. Here's a structured
approach to achieve both:
1. File Uploads with Express.js:
First, let's set up file uploads using Express.js with the help of multer, a popular
middleware for handling multipart/form-data:
Installation:
Ensure you have multer installed in your project:
npm install multer
Implementation:
const express = require('express');
const multer = require('multer');
const path = require('path');
const app = express();
// Serve static files from the 'public' directory
app.use(express.static('public'));
// Multer configuration for file uploads
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads'); // Directory where files will be stored
},
filename: function (req, file, cb) {
cb(null, Date.now() + path.extname(file.originalname)); // Unique
filename
}
});
const upload = multer({ storage: storage });
// Route to handle file upload
app.post('/upload', upload.single('file'), (req, res) => {
// Access uploaded file details via req.file
© Edunet Foundation. All rights reserved. | 344
res.json({ message: 'File uploaded successfully', filename:
req.file.filename });
});
// Serve static files from the 'uploads' directory
app.use('/uploads', express.static('uploads'));
// Error handling middleware
app.use((err, req, res, next) => {
console.error('Error occurred:', err);
res.status(500).json({ error: { message: 'Internal Server Error' } });
});
// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Create a Public Directory:
Create an upload.html file in the root of your project directory with the following content
to test the file upload:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>File Upload</title>
</head>
<body>
<h1>File Upload</h1>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<button type="submit">Upload</button>
</form>
</body>
</html>
Open your browser and navigate to http://localhost:3000/upload.html. Select a file and
click the "Upload" button.
Output:
© Edunet Foundation. All rights reserved. | 345
Explanation:
Multer Configuration (multer.diskStorage):
Configures multer to store uploaded files in the ./uploads directory.
Generates a unique filename for each uploaded file using the current timestamp
and original file extension.
File Upload Route (/upload):
Handles HTTP POST requests to /upload.
Uses upload.single('file') middleware to process single-file uploads with the field
name 'file'.
Responds with a JSON message containing the filename of the uploaded file.
Static File Serving (express.static):
Configures Express to serve static files (uploaded files) from the uploads
directory using the /uploads route.
Error Handling Middleware:
Catches and logs any errors that occur during request processing.
© Edunet Foundation. All rights reserved. | 346
Sends a generic error response (Internal Server Error) with a 500 status code.
2. Real-Time Features with WebSocket
Next, let's implement real-time features using WebSocket for bi-directional, full-duplex
communication between clients and the server:
Installation
Install ws, a WebSocket library for Node.js:
npm install ws
Implementation:
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
// WebSocket connection handling
wss.on('connection', (ws) => {
console.log('Client connected');
// Handle messages from clients
ws.on('message', (message) => {
console.log(`Received message: ${message}`);
// Broadcast message to all clients
wss.clients.forEach((client) => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
});
// Handle WebSocket closure
ws.on('close', () => {
console.log('Client disconnected');
});
});
// Serve static files (e.g., HTML, CSS, JS) from a directory
app.use(express.static('public'));
// Error handling middleware
© Edunet Foundation. All rights reserved. | 347
app.use((err, req, res, next) => {
console.error('Error occurred:', err);
res.status(500).json({ error: { message: 'Internal Server Error' } });
});
// Start server
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Explanation:
WebSocket Server Setup (new WebSocket.Server):
Creates a WebSocket server (wss) using the ws library on the same HTTP
server (server) as Express.
WebSocket Connection Handling (`wss.on('connection', ...) ):
Handles incoming WebSocket connections (ws represents a single client
connection).
Logs when a client connects ('connection' event).
Handles incoming messages ('message' event) from clients and broadcasts
them to all connected clients except the sender.
WebSocket Closure Handling (`ws.on('close', ...)):
Logs when a client disconnects ('close' event).
Static File Serving (express.static):
Serves static files (e.g., HTML, CSS, JS) from the public directory.
Clients can access these files to interact with the WebSocket server.
Error Handling Middleware:
Catches and logs any errors that occur during request processing.
Sends a generic error response (Internal Server Error) with a 500 status code.
Combining File Uploads and WebSocket
To combine file uploads with real-time features using WebSocket:
Integrate the file upload route (/upload) and WebSocket server in the same
Express application.
Ensure proper handling of WebSocket connections and messages to facilitate
real-time interactions alongside file uploads.
Following these steps, you can create an Express.js application that handles both file
uploads and real-time communication through WebSocket, providing a robust
foundation for interactive and dynamic web applications.
© Edunet Foundation. All rights reserved. | 348
Example:
Step 1: Create a Project Directory
Create a new directory for your project and navigate into it:
mkdir websocket-server
cd websocket-server
Step 2: Initialize the Project
Initialize a new Node.js project with the following command:
npm init -y
This will create a package.json file in your project directory.
Step 3: Install Dependencies
Install the required dependencies (express and ws):
npm install express ws
Step 4: Create the Server File
Create a file named server.js and copy the provided code into it:
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
// WebSocket connection handling
wss.on('connection', (ws) => {
console.log('Client connected');
// Handle messages from clients
ws.on('message', (message) => {
console.log(`Received message: ${message}`);
// Broadcast message to all clients
wss.clients.forEach((client) => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
});
© Edunet Foundation. All rights reserved. | 349
// Handle WebSocket closure
ws.on('close', () => {
console.log('Client disconnected');
});
});
// Serve static files (e.g., HTML, CSS, JS) from a directory
app.use(express.static('public'));
// Error handling middleware
app.use((err, req, res, next) => {
console.error('Error occurred:', err);
res.status(500).json({ error: { message: 'Internal Server Error' } });
});
// Start server
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
Step 5: Create a Public Directory
Create a directory named public in your project directory. This is where you will place
your static files (HTML, CSS, JS) that will be served by Express.
mkdir public
Step 6: Start the Server
Start the server by running the following command in your project directory:
node server.js
You should see an output indicating that the server is running:
Server is running on port 3000
Step 7: Test the WebSocket Server
Open your browser and navigate to http://localhost:3000 (assuming you have an
index.html file in the public directory). You can use WebSocket client tools or write
your own client-side JavaScript to test WebSocket connections.
Example Client-Side WebSocket Code (index.html)
Create an index.html file inside the public directory with the following content to test
the WebSocket connection:
<!DOCTYPE html>
<html lang="en">
<head>
© Edunet Foundation. All rights reserved. | 350
<meta charset="UTF-8">
<title>WebSocket Test</title>
</head>
<body>
<h1>WebSocket Test</h1>
<script>
const socket = new WebSocket('ws://localhost:3000');
socket.onopen = () => {
console.log('Connected to WebSocket server');
socket.send('Hello Server!');
};
socket.onmessage = (event) => {
console.log(`Message from server: ${event.data}`);
};
socket.onclose = () => {
console.log('Disconnected from WebSocket server');
};
socket.onerror = (error) => {
console.error('WebSocket error:', error);
};
</script>
</body>
</html>
Output:
© Edunet Foundation. All rights reserved. | 351
Chapter 8: MongoDB Fundamentals
Learning Outcomes:
Introduction to NoSQL databases.
Setting up MongoDB.
Understanding collections and documents.
CRUD operations in MongoDB.
Using Mongoose for MongoDB.
Connecting Node.js to MongoDB.
8.1 Introduction to NoSQL databases.
8.1.1 Overview
NoSQL is a type of database management system (DBMS) that is designed to
handle and store large volumes of unstructured and semi-structured data. Unlike
traditional relational databases that use tables with pre-defined schemas to store
data, NoSQL databases use flexible data models that can adapt to changes in data
structures and are capable of scaling horizontally to handle growing amounts of
data.
The term NoSQL originally referred to “non-SQL” or “non-relational” databases,
but the term has since evolved to mean “not only SQL,” as NoSQL databases have
expanded to include a wide range of different database architectures and data
models.
NoSQL databases are generally classified into four main categories:
1. Document databases: These databases store data as semi-structured
documents, such as JSON or XML, and can be queried using document-
oriented query languages.
2. Key-value stores: These databases store data as key-value pairs, and are
optimized for simple and fast read/write operations.
3. Column-family stores: These databases store data as column families,
which are sets of columns that are treated as a single entity. They are
optimized for fast and efficient querying of large amounts of data.
4. Graph databases: These databases store data as nodes and edges, and
are designed to handle complex relationships between data.
NoSQL databases are often used in applications where there is a high volume of
data that needs to be processed and analyzed in real-time, such as social media
analytics, e-commerce, and gaming. They can also be used for other applications,
such as content management systems, document management, and customer
relationship management.
However, NoSQL databases may not be suitable for all applications, as they may
not provide the same level of data consistency and transactional guarantees as
© Edunet Foundation. All rights reserved. | 352
traditional relational databases. It is important to carefully evaluate the specific
needs of an application when choosing a database management system.
NoSQL originally referring to non SQL or non relational is a database that
provides a mechanism for storage and retrieval of data. This data is modelled in
means other than the tabular relations used in relational databases. Such
databases came into existence in the late 1960s, but did not obtain the NoSQL
moniker until a surge of popularity in the early twenty-first century. NoSQL
databases are used in real-time web applications and big data and their use are
increasing over time.
NoSQL systems are also sometimes called Not only SQL to emphasize the
fact that they may support SQL-like query languages. A NoSQL database
includes simplicity of design, simpler horizontal scaling to clusters of
machines, has and finer control over availability. The data structures used
by NoSQL databases are different from those used by default in relational
databases which makes some operations faster in NoSQL. The suitability
of a given NoSQL database depends on the problem it should solve.
NoSQL databases, also known as “not only SQL” databases, are a new type
of database management system that has, gained popularity in recent
years. Unlike traditional relational databases, NoSQL databases are
designed to handle large amounts of unstructured or semi -structured data,
and they can accommodate dynamic changes to the data model. This
makes NoSQL databases a good fit for modern web applications, real-time
analytics, and big data processing.
Data structures used by NoSQL databases are sometimes also viewed as
more flexible than relational database tables. Many NoSQL stores
compromise consistency in favor of availability, speed,, and partition
tolerance. Barriers to the greater adoption of NoSQL stores include the use
of low-level query languages, lack of standardized interfaces, and huge
previous investments in existing relational databases.
Most NoSQL stores lack true ACID(Atomicity, Consistency, Isolation,
Durability) transactions but a few databases, such as MarkLogic, Aerospike,
FairCom c-treeACE, Google Spanner (though technically a NewSQL
database), Symas LMDB, and OrientDB have made them central to their
designs.
Most NoSQL databases offer a concept of eventual consistency in which
database changes are propagated to all nodes so queries for data might not
return updated data immediately or might result in reading data that is not
accurate which is a problem known as stale reads. Also,has some NoSQL
systems may exhibit lost writes and other forms of data loss. Some NoSQL
systems provide concepts such as write-ahead logging to avoid data loss.
One simple example of a NoSQL database is a document database. In a
document database, data is stored in documents rather than tables. Each
document can contain a different set of fields, making it easy to
accommodate changing data requirements.
For example, “Take, for instance, a database that holds data regarding
employees.”. In a relational database, this information might be stored in
tables, with one table for employee information and another table for
department information. In a document database, each employee would be
© Edunet Foundation. All rights reserved. | 353
stored as a separate document, with all of their information contained within
the document.
NoSQL databases are a relatively new type of database management
system that hasa gained popularity in recent years due to their scalability
and flexibility. They are designed to handle large amounts of unstructured
or semi-structured data and can handle dynamic changes to the data model.
This makes NoSQL databases a good fit for modern web applications, real -
time analytics, and big data processing.
8.1.2 Key Features of NoSQL:
1. Dynamic schema: NoSQL databases do not have a fixed schema and can
accommodate changing data structures without the need for migrations or
schema alterations.
2. Horizontal scalability: NoSQL databases are designed to scale out by
adding more nodes to a database cluster, making them well-suited for
handling large amounts of data and high levels of traffic.
3. Document-based: Some NoSQL databases, such as MongoDB, use a
document-based data model, where data is stored in a schema-less semi-
structured format, such as JSON or BSON.
4. Key-value-based: Other NoSQL databases, such as Redis, use a key-
value data model, where data is stored as a collection of key-value pairs.
5. Column-based: Some NoSQL databases, such as Cassandra, use a
column-based data model, where data is organized into columns instead of
rows.
6. Distributed and high availability: NoSQL databases are often designed
to be highly available and to automatically handle node failures and data
replication across multiple nodes in a database cluster.
7. Flexibility: NoSQL databases allow developers to store and retrieve data
in a flexible and dynamic manner, with support for multiple data types and
changing data structures.
8. Performance: NoSQL databases are optimized for high performance and
can handle a high volume of reads and writes, making them suitable for big
data and real-time applications.
8.1.3 Advantages of NoSQL:
There are many advantages of working with NoSQL databases such as MongoDB
and Cassandra. The main advantages are high scalability and high availability.
1. High scalability: NoSQL databases use sharding for horizontal scaling.
Partitioning of data and placing it on multiple machines in such a way that
the order of the data is preserved is sharding. Vertical scaling means adding
more resources to the existing machine whereas horizontal scaling means
adding more machines to handle the data. Vertical scaling is not that easy
to implement but horizontal scaling is easy to implement. Examples of
horizontal scaling databases are MongoDB, Cassandra, etc. NoSQL can
handle a huge amount of data because of scalability, as the data grows
NoSQL scalesThe auto itself to handle that data in an efficient manner.
© Edunet Foundation. All rights reserved. | 354
2. Flexibility: NoSQL databases are designed to handle unstructured or semi-
structured data, which means that they can accommodate dyna mic changes
to the data model. This makes NoSQL databases a good fit for applications
that need to handle changing data requirements.
3. High availability: The auto, replication feature in NoSQL databases makes
it highly available because in case of any failure data replicates itself to the
previous consistent state.
4. Scalability: NoSQL databases are highly scalable, which means that they
can handle large amounts of data and traffic with ease. This makes them a
good fit for applications that need to handle large amounts of data or traffic
5. Performance: NoSQL databases are designed to handle large amounts of
data and traffic, which means that they can offer improved performance
compared to traditional relational databases.
6. Cost-effectiveness: NoSQL databases are often more cost-effective than
traditional relational databases, as they are typically less complex and do
not require expensive hardware or software.
7. Agility: Ideal for agile development.
8.1.4 Disadvantages of NoSQL:
NoSQL has the following disadvantages.
1. Lack of standardization: There are many different types of NoSQL
databases, each with its own unique strengths and weaknesses. This lack
of standardization can make it difficult to choose the right database for a
specific application
2. Lack of ACID compliance: NoSQL databases are not fully ACID-
compliant, which means that they do not guarantee the consistency,
integrity, and durability of data. This can be a drawback for applications that
require strong data consistency guarantees.
3. Narrow focus: NoSQL databases have a very narrow focus as it is mainly
designed for storage but it provides very little functionality. Relational
databases are a better choice in the field of Transaction Management than
NoSQL.
4. Open-source: NoSQL is an databaseopen-source database. There is no
reliable standard for NoSQL yet. In other words, two database systems are
likely to be unequal.
5. Lack of support for complex queries: NoSQL databases are not designed
to handle complex queries, which means that they are not a good fit for
applications that require complex data analysis or reporting.
6. Lack of maturity: NoSQL databases are relatively new and lack the
maturity of traditional relational databases. This can make them less reliable
and less secure than traditional databases.
7. Management challenge: The purpose of big data tools is to make the
management of a large amount of data as simple as possible. But it is not
so easy. Data management in NoSQL is much more complex than in a
relational database. NoSQL, in particular, has a reputation for being
challenging to install and even more hectic to manage on a daily basis.
8. GUI is not available: GUI mode tools to access the database are not
flexibly available in the market.
© Edunet Foundation. All rights reserved. | 355
9. Backup: Backup is a great weak point for some NoSQL databases like
MongoDB. MongoDB has no approach for the backup of data in a consistent
manner.
10. Large document size: Some database systems like MongoDB and
CouchDB store data in JSON format. This means that documents are quite
large (Big Data, network bandwidth, speed), and having descriptive key
names actually hurts since they increase the document size.
8.1.5 Types of NoSQL database:
Types of NoSQL databases and the name of the database system that falls in that
category are:
1. Graph Databases: Examples – Amazon Neptune, Neo4j
2. Key value store: Examples – Memcached, Redis, Coherence
3. Column: Examples – Hbase, Big Table, Accumulo
4. Document-based: Examples – MongoDB, CouchDB, Cloudant
8.1.6 When should NoSQL be used:
1. When a huge amount of data needs to be stored and retrieved.
2. The relationship between the data you store is not that important
3. The data changes over time and is not structured.
4. Support of Constraints and Joins is not required at the database level
5. The data is growing continuously and you need to scale the database
regularly to handle the data.
In conclusion, NoSQL databases offer several benefits over traditional relational
databases, such as scalability, flexibility, and cost-effectiveness. However, they
also have several drawbacks, such as a lack of standardization, lack of ACID
compliance, and lack of support for complex queries. When choosing a database
for a specific application, it is important to weigh the benefits and drawbacks
carefully to determine the best fit.
8.2Setting up MongoDB
MongoDB is an open-source document-oriented database. It is categorized under
the NoSQL (Not only SQL) database because the storage and retrieval of data in
MongoDB are not in the form of tables. This is the general introduction to MongoDB
now we will learn how to install MongoDB in Windows.
You can install MongoDB using MSI. Let’s see a step-by-step instruction guide for
installing MongoDB in Windows using MSI.
Let’s see the MongoDB requirements for the installation of Windows.
8.2.1 Requirements to Install MongoDB on Windows
MongoDB 4.4 and later only support 64-bit versions of Windows.
MongoDB 7.0 Community Edition supports the following 64-bit versions of
Windows on x86_64 architecture:
© Edunet Foundation. All rights reserved. | 356
o Windows Server 2022
o Windows Server 2019
o Windows 11
Ensure that the user is running mongod and mongos has the necessary
permissions from the following groups:
o Performance Monitor Users
o Performance Log Users
Steps to Install MongoDB on Windows using MSI
To install MongoDB on Windows, first, download the MongoDB server and then
install the MongoDB shell. The Steps below explain the installation process in
detail and provide the required resources for the smooth download and install
MongoDB.
Step 1: Go to the MongoDB Download
Centre (https://www.mongodb.com/try/download/community) to download the
MongoDB Community Server.
Figure 91. MongoDB Download
Here, you can select any version, Windows, and package(msi) according to your
requirement. For Windows, we need to choose:
Version: 7.0.4
OS: Windows x64
Package: msi
Step 2: When the download is complete open the msi file and click the next
button in the startup screen:
© Edunet Foundation. All rights reserved. | 357
Figure 92. MongoDB Setup
Step 3: Now accept the End-User License Agreement and click the next button:
Figure 93. MongoB Service Configuration
© Edunet Foundation. All rights reserved. | 358
Step 4: Now select the complete option to install all the program features. Here, if
you can want to install only selected program features and want to select the
location of the installation, then use the Custom option:
Figure 94. MongoDB Setup Type
Step 5: Select “Run service as Network Service user” and copy the path of the
data directory. Click Next:
Figure 95. Service Configuration
© Edunet Foundation. All rights reserved. | 359
Step 6: Click the Install button to start the MongoDB installation process:
Figure 96. MongoDB install
Step 7: After clicking on the install button installation of MongoDB begins:
Figure 97. MongoDB Installing
© Edunet Foundation. All rights reserved. | 360
Step 8: Now click the Finish button to complete the MongoDB installation
process:
Step 9: Now we go to the location where MongoDB installed in step 5 in your
system and copy the bin path:
Figure 98. Copy the bin path
Step 10: Now, to create an environment variable open system property >>
Environment Variable >> System variable >> path >> Edit Environment variable
and paste the copied link to your environment system and click Ok:
Figure 99. Edit Environment Variable
© Edunet Foundation. All rights reserved. | 361
Step 11: After setting the environment variable, we will run the MongoDB server,
i.e. mongod. So, open the command prompt and run the following command:
Mongod.
When you run this command you will get an error i.e. C:/data/db/ not found.
Step 12: Now, Open C drive and create a folder named “data” inside this folder
create another folder named “db”. After creating these folders. Again open the
command prompt and run the following command:
Mongod
Now, this time the MongoDB server(i.e., mongod) will run successfully.
Figure 100.. Check MongoDB in Command Prompt
Important Point:
To execute mongo db commands in our local machine we require mongo shell
installation is required. So that we need to install mongo shell application software
in our local machine.
Download and install mongo Shell in windows:
Step13: Open browser and type https://www.mongodb.com/try/download/shell
The above url then we are getting below window and select package as msi and
click on download option.
© Edunet Foundation. All rights reserved. | 362
Figure 101. Download MongoDB
Step14: click on next button
Figure 102. MongoDB Shell Setup
© Edunet Foundation. All rights reserved. | 363
Step15: Again, click on next button for destination folder
Figure 103. MongoDB choose directory
Step16: click on install button to install mongo shell
Figure 104. MongoDB choose directory
© Edunet Foundation. All rights reserved. | 364
Step17: Open command prompt and type command as mongosh and find the
version about MongoDB and Mongosh & url.
Note: Here by default test database created.
Figure 105. MongoDB Shell
Now, you are ready to write queries in the mongo Shell.
Run MongoDB
Now you can make a new database, collections, and documents in your shell.
Below is an example of how to make a new database:
Use command:
use Database_name command makes a new database in the system if it does not
exist, if the database exists it uses that database:
ex: use Edunet
test> use Edunet
switched to db Edunet
Edunet>
Hence MongoDB is successfully installed and its working absolutely perfect!
8.2 Understanding collections and documents.
Databases, collections, documents are important parts of MongoDB without them you
are not able to store data on the MongoDB server.
A Database contains a collection, and a collection contains documents and the
documents contain data, they are related to each other.
© Edunet Foundation. All rights reserved. | 365
Figure 106. Structure of MongoDB
Database
In MongoDB, a database contains the collections of documents. One can create
multiple databases on the MongoDB server.
View Databases:
To see how many databases are present in your MongoDB server, write the following
statement in the mongo shell:
show dbs or show databases;
For Example:
Figure 107. Show database
© Edunet Foundation. All rights reserved. | 366
Note: Here, we freshly started MongoDB so we do not have a database except these
three default databases, i.e, admin, config, and local.
Naming Restriction for Database:
Before creating a database you should first learn about the naming restrictions for
databases:
In MongoDB, the names of the database are case insensitive, but you must
always remember that the database names cannot differ only by the case of
the characters.
For windows user, MongoDB database names cannot contain any of these
following characters:
/\. "$*:|?
For Unix and Linux users, MongoDB database names cannot contain any of
these following characters:
/\. "$
MongoDB database names cannot contain null characters (in windows, Unix,
and Linux systems).
MongoDB database names cannot be empty and must contain less than 64
characters.
Creating Database:
In the mongo shell, you can create a database with the help of the following
command:
use database_name;
This command actually switches you to the new database if the given name does not
exist and if the given name exists, then it will switch you to the existing database.
Now at this stage, if you use the show command to see the database list where you
will find that your new database is not present in that database list because, in
MongoDB, the database is actually created when you start entering data in that
database.
For Example:
Figure 108. Show dbs
© Edunet Foundation. All rights reserved. | 367
Here, we create a new database named tsp using the use command. After creating a
database when we check the database list we do not find our database on that list
because we do not enter any data in the tsp database.
Collection
Collections are just like tables in relational databases, they also store data, but in the
form of documents. A single database is allowed to store multiple collections.
Schemaless:
As we know that MongoDB databases are schema less. So, it is not necessary in a
collection that the schema of one document is similar to another document.
Or in other words, a single collection contains different types of documents like as
shown in the below example where Edunet-> emp-> collection contain two different
types of documents:
Figure 109. find method
Naming Restrictions for Collection:
Before creating a collection you should first learn about the naming restrictions for
collections:
Collection name must starts with an underscore or a character.
Collection name does not contain $, empty string, null character and does not
begin with system. prefix.
The maximum length of the collection name is 120 bytes(including the database
name, dot separator, and the collection name).
Creating collection:
After creating database now we create a collection to store documents. The collection
is created using the following syntax:
db.collection_name.insertOne({..})
© Edunet Foundation. All rights reserved. | 368
Here, insertOne( ) function is used to store single data in the specified collection. And
in the curly braces { } we store our data or in other words, it is a document.
For Example:
Figure 110. insertOne method
In this example, we create a collection named as the emp and we insert data in it with
the help of insertOne() function. Or in other words, {empId: 103} is a document in the
emp collection, and in this document, the empId is the key or field and 103 is the value
of this key or field.
After pressing enter we got a message (as shown in the above image) and this
message tells us that the data enters successfully (i.e., “acknowledge”: true) and also
assigns us an automatically created id. It is the special feature provided by MongoDB
that every document provided a unique id and generally, this id is created
automatically, but you are allowed to create your own id (must be unique).
Document
In MongoDB, the data records are stored as BSON documents. Here, BSON stands
for binary representation of JSON documents, although BSON contains more data
types as compared to JSON. The document is created using field-value pairs or key-
value pairs and the value of the field can be of any BSON type.
Syntax:
{
field1: value1
field2: value2
....
fieldN: valueN
}
© Edunet Foundation. All rights reserved. | 369
Naming restriction of fields:
Before moving further first you should learn about the naming restrictions for fields:
The field names are of strings.
The _id field name is reserved to use as a primary key. And the value of this
field must be unique, immutable, and can be of any type other than an array.
The field name cannot contain null characters.
The top-level field names should not start with a dollar sign ($).
Document Size: The maximum size of the BSON document is 16MB. It ensures that
the single document does not use too much amount of RAM or bandwidth (during
transmission). If a document contains more data than the specified size, then
MongoDB provides a GridFS API to store such type of documents.
Important Notes –
A single document may contain duplicate fields.
MongoDB always saves the order of the fields in the documents except for the
_id field (which always comes in the first place) and the renaming of fields may
change the order of the fields in the documents.
_id Field: In MongoDB, every document store in the collection must contain a
unique _id field it is just like a primary key in a relational database. The value
of the _id field can be set by the user or by the system (if the user does not
create an _id field, then the system will automatically generate an ObjectId for
_id field).
o When you create a collection MongoDB automatically creates a unique
index on the _id field.
o The _id field is the first field of every document.
o The value of the _id field can be of any BSON type except arrays.
o The default value of the _id field is ObjectId.
Example #1:
Here, empId, empName fields in emp collection. It contain empId is numeric value,
empName contain String value.
© Edunet Foundation. All rights reserved. | 370
8.3 CRUD operations in MongoDB.
CRUD Operations (Create, Read, Update, and Delete) are the basic set of operations
that allow users to interact with the MongoDB server.
As we know, to use MongoDB we need to interact with the MongoDB server to perform
certain operations like entering new data into the application, updating data into the
application, deleting data from the application, and reading the application data.
In this article, we will learn all 4 major operations– CREATE, READ, UPDATE,
and DELETE that form the CRUD operations in MongoDB.
Perform CRUD Operations in MongoDB
Now that we know the components of the CRUD operation, let’s learn about each
individual operation in MongoDB. We will know what each operation does, and the
methods to perform these operations in MongoDB.
We will create, read, update and delete documents from MongoDB server.
8.4.1 Create Operations
The create or insert operations are used to insert or add new documents in the
collection. If a collection does not exist, then it will create a new collection in the
database.
You can perform, create operations using the following methods provided by the
MongoDB:
Method Description
db.collection.insertOne( ) It is used to insert a single document in the collection.
db.collection.insertMany( ) It is used to insert multiple documents in the collection.
db.createCollection( ) It is used to create an empty collection.
© Edunet Foundation. All rights reserved. | 371
Create Operations Example
Let’s look at some examples of the Create operation from CRUD in MongoDB.
Example 1: In this example, we are inserting details of a single student in the form of
document in the student collection using db.collection.insertOne() method.
Figure 111. insertOne-multiple data
Example 2: In this example, we are inserting details of the multiple students in the
form of documents in the student collection using db.collection.insertMany()
method.
Figure 112. insertMany-multiple data
© Edunet Foundation. All rights reserved. | 372
8.4.2 Read Operations
The Read operations are used to retrieve documents from the collection, or in other
words, read operations are used to query a collection for a document.
You can perform read operation using the following method provided by the MongoDB:
Method Description
db.collection.find( ) It is used to retrieve documents from the collection.
Note: pretty() method is used to decorate the result such that it is easy to read.
Read Operations Example
Let’s look at some examples of Read operation from CRUD in MongoDB.
Example: In this example, we are retrieving the details of students from the student
collection using db.collection.find( ) method.
Figure 113. find-multiple data
8.4.3 Update Operations
The update operations are used to update or modify the existing document in the
collection. You can perform update operations using the following methods provided
by the MongoDB:
© Edunet Foundation. All rights reserved. | 373
Method Description
It is used to update a single document in the collection that
db.collection.updateOne() satisfy the given criteria.
It is used to update multiple documents in the collection
db.collection.updateMany() that satisfy the given criteria.
It is used to replace single document in the collection that
db.collection.replaceOne() satisfy the given criteria.
Update Operations Example
Let’s look at some examples of the update operation from CRUD in MongoDB.
Example 1: In this example, we are updating the age of Sumit in the student
collection using db.collection.updateOne() method.
Figure 114. UpdateOne()
Example 2: In this example, we are updating the year of course in all the documents
in the student collection using db.collection.updateMany() method.
© Edunet Foundation. All rights reserved. | 374
Figure 115. UpdateMany()
8.4.4 Delete Operations
The delete operation are used to delete or remove the documents from a collection.
You can perform delete operations using the following methods provided by the
MongoDB:
Method Description
It is used to delete a single document from the collection that
db.collection.deleteOne() satisfy the given criteria.
© Edunet Foundation. All rights reserved. | 375
Method Description
It is used to delete multiple documents from the collection
db.collection.deleteMany() that satisfy the given criteria.
Delete Operations Examples
Let’s look at some examples of delete operation from CRUD in MongoDB.
Example 1: In this example, we are deleting a document from the student collection
using db.collection.deleteOne() method.
Figure 116. deleteOne()
Example 2: In this example, we are deleting all the documents from the student
collection using db.collection.deleteMany() method.
© Edunet Foundation. All rights reserved. | 376
Figure 117. deleteMany()
8.4 Connecting Node.js to MongoDB.
Mongoose is a popular Object Data Modelling (ODM) library for MongoDB in the
Node.js ecosystem. It provides an elegant way to define schemas, models, and handle
data validation and manipulation. Here’s a deeper dive into Mongoose and how it
enhances working with MongoDB.
What is Mongoose?
Mongoose is an ODM library for MongoDB and Node.js, designed to provide a higher
level of abstraction for interacting with MongoDB databases. It helps in defining
schemas, applying data validation, and enforcing a consistent data structure.
Why Use Mongoose?
While MongoDB offers a flexible schema-less structure, many developers prefer the
predictability and structure of schemas. Mongoose enforces a schema on the data,
ensuring that all documents in a collection adhere to a defined structure. This semi-
rigid schema can help prevent inconsistencies and make data management more
predictable.
Key Features of Mongoose
© Edunet Foundation. All rights reserved. | 377
1. Schema Definition: Mongoose schemas define the structure of documents in
a collection. Fields and their data types are specified, ensuring uniformity.
2. Model Creation: Models in Mongoose use schemas to apply the defined
structure to each document. They handle CRUD operations (Create, Read,
Update, Delete) efficiently.
3. Validation: Mongoose provides robust validation, ensuring data integrity by
enforcing constraints such as required fields, data types, and custom validation
logic.
4. Middleware: Mongoose allows the use of middleware (pre and post hooks) for
functions like validation, saving, and removing documents.
Setting Up Mongoose
Here’s a step-by-step guide to setting up and using Mongoose in a Node.js project:
Step 1: Environment Setup
Assuming you have Node.js installed, set up your project directory and install the
necessary packages.
mkdir backend
cd backend
install below libraries in C:\>backend\(folder)
npm init -y
npm install mongoose // to connect mongodb
npm install nodemon // used for auto restart project
npm intsall express //used for API calls
npm install cors //used for connecting backend to frontend
npm install body-parser //used for all CRUD data application
type
code . (dot operator)
open VSCode Editor
In your package.json, add a script to run the project using Nodemon and specify the
module type to use Module.
{
"name": "backend",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon index.js"
},
"keywords": [],
© Edunet Foundation. All rights reserved. | 378
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"mongoose": "^8.4.4"
},
"devDependencies": {
"nodemon": "^3.1.4"
}
}
Step 2: Connecting to MongoDB
Create an index.js file and connect to your MongoDB instance using Mongoose.
Create .env file and type the below code and save.
.env:
PORT=5000
MONGOURL="mongodb+srv://ajay4rjava:[email protected]
b.net/crudapp?retryWrites=true&w=majority&appName=Cluster0"
Index.js:
const PORT=process.env.PORT || 7000;
const URL=process.env.MONGOURL;
mongoose.connect(URL).then(()=>{
console.log("db connected successfully");
app.listen(PORT,()=>{
console.log(`Server is running on ${PORT}`)
})
}).catch(error=>console.log(error));
Step 3: Creating a Schema of a Model
Define a schema and create a model in models “UserModel.js”
import mongoose from "mongoose"
const userSchema=new mongoose.Schema(
{
fname:{
type:String,
required:true
© Edunet Foundation. All rights reserved. | 379
},
lname:{
type:String,
required:true
},
email:{
type:String,
required:true
},
password:{
type:String,
required:true
}
}
)
export default mongoose.model("User",userSchema);
Step 4: Create a landing page index.js
import express from "express";
import mongoose from "mongoose";
import bodyParser from "body-parser";
import dotenv from "dotenv";
import cors from "cors";
import route from "./routes/UserRoute.js";
const app=express();
app.use(bodyParser.json());
app.use(cors());
dotenv.config();
const PORT=process.env.PORT || 7000;
const URL=process.env.MONGOURL;
mongoose.connect(URL).then(()=>{
console.log("db connected successfully");
app.listen(PORT,()=>{
console.log(`Server is running on ${PORT}`)
})
}).catch(error=>console.log(error));
app.use("/api",route);
© Edunet Foundation. All rights reserved. | 380
Step 5: Inserting Data
export const create=async(req,res)=>{
try{
const userData=new User(req.body);
if(!userData){
return res.status(404).json({msg:"user data not found"});
}
const savedData=await userData.save();
res.status(200).json(savedData)
}
catch(error){
res.status(500).json({error:error});
}
}
Step 6: Finding Data
Retrieve documents from the database using various methods.
export const getAll=async(req,res)=>{
try{
const userData=await User.find( );
if(!userData){
return res.status(404).json({msg:"user data not found"})
}
res.status(200).json(userData)
}
catch(error){
res.status(500).json({error:error});
}
}
Step 7: Updating Data
Update existing documents.
export const update=async(req,res)=>{
try{
const id=req.params.id;
const userExist=await User.findById(id);
if(!userExist){
return res.status(404).json({msg:"user not found"})
}
const updatedData=await User.findByIdAndUpdate(id, req.body, {new: true})
res.status(200).json({msg:"User updated successfully"})
}
catch(error){
© Edunet Foundation. All rights reserved. | 381
res.status(500).json({error:error})
}
}
Step 8: Deleting Data
Delete documents from the database.
export const deleteUser=async(req,res)=>{
try{
const id=req.params.id;
const userExist=await User.findById(id);
if(!userExist){
return res.status(404).json({msg:"user not exist"})
}
await User.findByIdAndDelete(id); //deleting data based on id
res.status(200).json({msg:"user deleted successfully"})
}
catch(error){
res.status(500).json({error:error});
}
}
How to Connect Node to a MongoDB Database?
Example: Below is the code example of how to connect node.js to a mongodb
database.
import express from "express";
import mongoose from "mongoose";
import bodyParser from "body-parser";
import dotenv from "dotenv";
import cors from "cors";
const app=express();
app.use(bodyParser.json());
app.use(cors());
dotenv.config();
const PORT=process.env.PORT || 7000;
const URL=process.env.MONGOURL;
mongoose.connect(URL).then(()=>{
© Edunet Foundation. All rights reserved. | 382
console.log("db connected successfully");
app.listen(PORT,()=>{
console.log(`Server is running on ${PORT}`)
})
}).catch(error=>console.log(error));
Output:
> nodemon index.js
[nodemon] 3.1.4
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,cjs,json
[nodemon] starting `node index.js`
db connected successfully
Server is running on 5000
© Edunet Foundation. All rights reserved. | 383
Chapter 9: Connecting Frontend with Backend
Learning Outcomes:
Planning a full-stack application
Setting up the project structure
Integrating all MERN components
Making HTTP requests from React using Axios or Fetch
Connecting all parts (Connecting frontend to backend API)
Deployment strategies (Netlify for frontend, Render for backend,
GitHub Pages)
9.1 Planning a Full-Stack Application
Planning a full-stack application is a critical phase that involves several steps to ensure
that the project is well-defined, manageable, and aligns with your goals. Here's a
detailed guide to planning a full-stack application:
9.1.1 Define the Project Scope
Objective: Clearly articulate the primary purpose and goals of the application.
Features: List the key features and functionalities the application will include.
User Roles: Identify different types of users and their permissions (e.g., admin,
user, guest).
Non-Functional Requirements: Consider performance, security, scalability,
and maintainability aspects.
9.1.2 Design the Architecture
System Architecture: Create a high-level diagram showing the interaction
between the frontend, backend, database, and any third-party services.
Data Flow: Define how data will flow through the system from user interactions
to data storage and processing.
Technology Stack: Confirm the technologies you will use (e.g., React for
frontend, Node.js/Express for backend, MongoDB for the database).
9.1.3 Create User Stories and Wireframes
User Stories: Write user stories to capture user interactions with the
application. User stories typically follow the format: "As a [user type], I want to
[action] so that [benefit]."
o Example: "As a user, I want to create an account so that I can save my
preferences."
© Edunet Foundation. All rights reserved. | 384
Wireframes: Design wireframes for the user interface. These are basic
sketches of the UI layout and elements, focusing on user experience and
navigation.
o Tools: You can use tools like Balsamiq, Sketch, Figma, or Adobe XD for
wireframing.
9.1.4 Identify Technical Requirements
Database Design: Plan the database schema, including collections (tables),
fields, relationships, and indexes.
API Design: Outline the RESTful API endpoints that the backend will expose,
including the request and response formats.
o Example: GET /api/items to fetch a list of items, POST /api/items to
create a new item.
Frontend Components: Identify the main components needed in your React
application and how they will interact.
o Example: Navigation bar, item list, item detail view, form for
adding/editing items.
9.1.5 Define Milestones and Timeline
Phases: Break down the project into phases such as planning, design,
development, testing, and deployment.
Milestones: Set specific, measurable milestones for each phase.
o Example: "Complete user authentication system by [date]."
Timeline: Create a project timeline with deadlines for each milestone to ensure
steady progress.
9.1.6 Set Up a Project Management Workflow
Tools: Choose project management tools like Trello, Jira, or Asana to track
tasks and progress.
Tasks: Break down each milestone into actionable tasks and assign them to
team members.
Communication: Establish clear communication channels for the team using
tools like Slack, Microsoft Teams, or email.
9.1.7 Risk Management
Identify Risks: List potential risks that could affect the project, such as
technical challenges, resource limitations, or scope creep.
Mitigation Plan: Develop strategies to mitigate identified risks. For example,
plan for extra time to handle unexpected technical issues.
9.1.8 Plan for Testing and Quality Assurance
Testing Strategy: Define how you will test the application, including unit tests,
integration tests, and end-to-end tests.
Tools: Identify testing tools and frameworks (e.g., Jest for unit testing in React,
Mocha for backend testing).
Quality Assurance: Establish QA processes to ensure that the application
meets all requirements and works correctly across different devices and
browsers
© Edunet Foundation. All rights reserved. | 385
9.2 Setting up the project structure
1. Create the Project Directory
First, create the root directory for your project:
mkdir crud_mern
cd crud_mern
code . (open in VScode)
2. Backend Setup
Create backend directory:
Create a folder for backend like folder name as “backend”
mkdir backend
cd backend
npm init -y
Install Dependencies
Install the necessary dependencies for the backend:
npm install express
npm install mongoose
npm install cors
npm install body-parser
npm install dotenv
npm install --save-dev nodemon
Create the Directory Structure
Create a structured directory layout for the backend:
mkdir models routes controllers
Figure 118. Project Structure
© Edunet Foundation. All rights reserved. | 386
Create a landing page in backend:
index.js: The main entry point for the server.
import express from "express";
import mongoose from "mongoose";
import bodyParser from "body-parser";
import dotenv from "dotenv";
import cors from "cors";
import route from "./routes/UserRoute.js";
const app=express();
app.use(bodyParser.json());
app.use(cors());
dotenv.config();
const PORT=process.env.PORT || 7000;
const URL=process.env.MONGOURL;
mongoose.connect(URL).then(()=>{
console.log("db connected successfully");
app.listen(PORT,()=>{
console.log(`Server is running on ${PORT}`)
})
}).catch(error=>console.log(error));
app.use("/api",route);
Create “.env” file for configuration :
.env
PORT=5000
MONGOURL="mongodb+srv://ajay4rjava:[email protected]
b.net/crudapp?retryWrites=true&w=majority&appName=Cluster0"
models/UserModel.js:
Mongoose schema and model for items.
import mongoose from "mongoose"
const userSchema=new mongoose.Schema(
{
fname:{
© Edunet Foundation. All rights reserved. | 387
type:String,
required:true
},
lname:{
type:String,
required:true
},
email:{
type:String,
required:true
},
password:{
type:String,
required:true
}
}
)
export default mongoose.model("User",userSchema)
routes/UserRoute.js: Define API routes for items.
import express from 'express'
import {create, getAll, getOne, update, deleteUser} from
../controller/UserController.js';
const route=express.Router();
route.post("/create",create);
route.get("/getall",getAll);
route.get("/getone/:id",getOne);
route.put("/update/:id",update);
route.delete("/delete/:id", deleteUser);
export default route;
controller/UserController.js:
Define main logic for the application
import User from "../models/UserModel.js"
export const create=async(req,res)=>{
try{
const userData=new User(req.body);
if(!userData){
return res.status(404).json({msg:"user data not found"});
}
const savedData=await userData.save();
res.status(200).json(savedData)
}
catch(error){
© Edunet Foundation. All rights reserved. | 388
res.status(500).json({error:error});
}
}
export const getAll=async(req,res)=>{
try{
const userData=await User.find();
if(!userData){
return res.status(404).json({msg:"user data not found"})
}
res.status(200).json(userData)
}
catch(error){
res.status(500).json({error:error});
}
}
export const getOne=async(req,res)=>{
try{
const id=req.params.id;
const userExist=await User.findById(id);
if(!userExist){
return res.status(404).json({msg:"user not found"})
}
res.status(200).json(userExist);
}
catch(error){
res.status(500).json({error:error})
}
}
export const update=async(req,res)=>{
try{
const id=req.params.id;
const userExist=await User.findById(id);
if(!userExist){
return res.status(404).json({msg:"user not found"})
}
const updatedData=await User.findByIdAndUpdate(id, req.body, {new: true})
res.status(200).json({msg:"User updated successfully"})
}
catch(error){
res.status(500).json({error:error})
}
}
export const deleteUser=async(req,res)=>{
try{
© Edunet Foundation. All rights reserved. | 389
const id=req.params.id;
const userExist=await User.findById(id);
if(!userExist){
return res.status(404).json({msg:"user not exist"})
}
await User.findByIdAndDelete(id);
res.status(200).json({msg:"user deleted successfully"})
}
catch(error){
res.status(500).json({error:error});
}
}
Add ThunderClient plugin in VSCode IDE
To test API Calls which we need to install ThunderClient plugins in VSCode. So that
click on extensions option from VSCode at left hand side panel and type in search
bar as Thunder Client and then click install option to install Thunder Client.
Figure 119. ThunderClient Plugin
Check API Calls working : post
Figure 120. POST API CALL
© Edunet Foundation. All rights reserved. | 390
Check API Calls working : getAll (fetch All records)
Figure 121. getAll API call
Check API Calls working : getOne (fetch only one record)
Figure 122. getOne API call
Check API Calls working : update (edit only one record)
Figure 123. Update API call
© Edunet Foundation. All rights reserved. | 391
Check API Calls working : delete (delete only one record)
Figure 124. Delete API call
3. Frontend Setup
Create a React Application
Navigate back to the root directory i.e “crud_mern” and create a new React application:
npx create-react-app frontend
cd frontend
Install Dependencies
Install any additional dependencies
npm install axios
npm Install react-router-dom
Create the Directory Structure
Organize your React project directory:
mkdir src/components
src/components/adduser
src/components/getuser
src/components/updateuser
Example File Contents
src/app.js: Main React component.
import './App.css';
import {RouterProvider, createBrowserRouter} from 'react-router-dom'
import User from './components/getuser/User';
import Add from './components/adduser/Add';
import Edit from './components/updateuser/Edit';
function App() {
const route=createBrowserRouter([
{
© Edunet Foundation. All rights reserved. | 392
path:"/",
element: <User/>
},
{
path:"/add",
element: <Add/>
},
{
path:"/edit/:id",
element: <Edit/>
},
])
return (
<div className="App">
<RouterProvider router={route}>
</RouterProvider>
</div>
);
}
export default App;
src/components/adduser/add.jsx:
import React, {useState} from 'react'
import { Link, useNavigate } from 'react-router-dom'
import "./Add.css"
import axios from "axios"
import toast from "react-hot-toast"
const Add = () => {
const users={
fname:"",
lname:"",
email:"",
password:""
}
const [user, setUser]=useState(users);
const navigate=useNavigate();
const inputHandler=(e)=>{
const{name, value}=e.target;
setUser({...user,[name]:value});
}
const submitForm=async(e)=>{
e.preventDefault();
© Edunet Foundation. All rights reserved. | 393
await axios.post("http://localhost:5000/api/create",user)
.then((response)=>{
toast.success(response.data.msg,{position:"top-right"})
navigate("/")
}).catch(error=>console.log(error))
}
return (
<div className='addUser'>
<Link to={"/"}>Back</Link>
<h3>Add new user</h3>
<form className='addUserForm' onSubmit={submitForm}>
<div className='inputGroup'>
<label htmlFor='fname'>First Name</label>
<input type="text" onChange={inputHandler} id="fname" name="fname"
autoComplete='off' placeholder='first name'/>
</div>
<div className='inputGroup'>
<label htmlFor='lname'>Last Name</label>
<input type="text" onChange={inputHandler} id="lname" name="lname"
autoComplete='off' placeholder='last name'/>
</div>
<div className='inputGroup'>
<label htmlFor='email'>Email</label>
<input type="email" onChange={inputHandler} id="email" name="email"
autoComplete='off' placeholder='Email'/>
</div>
<div className='inputGroup'>
<label htmlFor='password'>Password</label>
<input type="password" onChange={inputHandler} id="password"
name="password" autoComplete='off' placeholder='Password'/>
</div>
<div className='inputGroup'>
<button type="submit">ADD USER</button>
</div>
</form>
</div>
)
}
export default Add
src/components/adduser/add.css:
.addUser{
width:25%;
background-color: white;
box-shadow: 10px 10px 8px rgba(red, green, blue, alpha);
© Edunet Foundation. All rights reserved. | 394
border-radius: 5px;
margin: 50px auto;
padding: 50px;
}
.addUserForm{
margin-top: 20px;
}
.addUserForm .inputGroup{
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
}
.addUserForm .inputGroup label{
margin-bottom: 5px;
}
.addUserForm .inputGroup input{
margin-bottom: 10px;
padding: 10px;
outline: none;
}
.addUserForm .inputGroup button{
border: 0;
outline: none;
background-color: purple;
color: white;
padding: 20px;
cursor: pointer;
}
src/components/getuser/User.jsx:
import React, { useEffect, useState} from 'react'
import "./User.css"
import { Link } from 'react-router-dom'
import axios from "axios"
const User = () => {
const [users,setUsers]=useState([]);
useEffect(()=>{
const fetchData=async()=>{
const response= await axios.get("http://localhost:5000/api/getall")
setUsers(response.data)
© Edunet Foundation. All rights reserved. | 395
}
fetchData();
},[])
const deleteUser=async(userId)=>{
await axios.delete(`http://localhost:5000/api/delete/${userId}`)
.then((response)=>{
setUsers((prevUser)=>prevUser.filter((user)=>user._id !== userId))
}).catch((error)=>{
console.log(error);
})
}
return (
<div className='userTable'>
<Link to={"/add"} className='addButton'>Add User</Link>
<table border={1} cellSpacing={0} cellPadding={10}>
<thead>
<tr>
<th>S.No</th>
<th>User Name</th>
<th>Email</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{
users.map((user,index)=>{
return(
<tr key={user._id}>
<td>{index +1}</td>
<td>{user.fname}{user.lname}</td>
<td>{user.email}</td>
<td className='actionButtons'>
<button onClick={()=>deleteUser(user._id)}>Delete</button>
<Link to={`/edit/`+user._id}>Edit</Link>
</td>
</tr>
)
})
}
</tbody>
</table>
</div>
)
}
© Edunet Foundation. All rights reserved. | 396
export default User
src/components/getuser/User.css:
.userTable{
width: 60%;
background-color: white;
box-shadow: 10px 10px 8px rgba(red, green, blue, alpha);
border-radius: 5px;
margin: 50px auto;
padding: 50px;
}
.addButton{
text-decoration: none;
background-color: purple;
color:white;
font-weight: 500;
box-shadow: 1px 1px 8px rgba(red, green, blue, alpha);
border-radius: 5px;
padding: 10px;
}
.userTable table{
width: 100%;
margin-top: 30px;
border-collapse: collapse;
}
.userTable table thead th{
background-color: blue;
color: white;
padding: 10px;
}
.userTable table tbody td{
padding: 10px;
text-align: center;
}
.actionButtons button{
border:0;
outline:none;
background-color: red;
padding: 8px 10px;
color: white;
border-radius: 5px;
}
.actionButtons a{
background-color: cadetblue;
padding: 8px 10px;
© Edunet Foundation. All rights reserved. | 397
color: white;
border-radius: 5px;
margin: 0 10px;
}
src/components/updateuser/Edit.jsx:
import React,{useEffect, useState} from 'react'
import { Link, useNavigate, useParams } from 'react-router-dom';
import "../adduser/Add.css"
import axios from "axios"
import toast from "react-hot-toast"
const Edit = () => {
const users={
fname:"",
lname:"",
email:"",
}
const {id}=useParams();
const navigate=useNavigate();
const [user,setUser]=useState(users);
const inputChangeHandler=(e)=>{
const {name,value}=e.target;
setUser({...user,[name]:value});
}
useEffect(()=>{
axios.get(`http://localhost:5000/api/getone/${id}`)
.then((response)=>{
setUser(response.data)
}).catch((error)=>{
console.log(error);
})
},[id])
const submitForm=async(e)=>{
e.preventDefault();
await axios.put(`http://localhost:5000/api/update/${id}`,user)
.then((response)=>{
toast.success(response.data.msg,{position:"top-right"})
navigate("/")
}).catch(error=>console.log(error))
© Edunet Foundation. All rights reserved. | 398
}
return (
<div className='addUser'>
<Link to={"/"}>Back</Link>
<h3>Update user</h3>
<form className='addUserForm' onSubmit={submitForm}>
<div className='inputGroup'>
<label htmlFor='fname'>First Name</label>
<input type="text" value={user.fname} onChange={inputChangeHandler}
id="fname" name="fname" autoComplete='off' placeholder='first name'/>
</div>
<div className='inputGroup'>
<label htmlFor='lname'>Last Name</label>
<input type="text" value={user.lname} onChange={inputChangeHandler}
id="lname" name="lname" autoComplete='off' placeholder='last name'/>
</div>
<div className='inputGroup'>
<label htmlFor='email'>Email</label>
<input type="email" value={user.email} onChange={inputChangeHandler}
id="email" name="email" autoComplete='off' placeholder='Email'/>
</div>
<div className='inputGroup'>
<button type="submit">UPDATE USER</button>
</div>
</form>
</div>
)
}
export default Edit
OUTPUT:
© Edunet Foundation. All rights reserved. | 399
9.3 Deployment:
9.3.1 Deploying on GitHub Pages
Steps to Deploy MERN stack project into Rendor.com
o Push the project from the VSCode into github
o Create account in rendor.com
o Deploy first backend application project
o Add backend successful deploy URL in frontend code
o Deploy frontend application project
o Check frontend URL in browser working or not.
1.Push the project from the VSCode into github:
open github.com, and click on new button to create a new
repository.
In the below example Repository name as “CRUD_APP”.
Click on Create repository
Figure 125. Push Project in github
o goto VSCode main root project and initialize git into that folder.
© Edunet Foundation. All rights reserved. | 400
Figure 126. initialize git
type command as git status to check untracked files & directories
Figure 127. git status
To change tracked files and directories
Type command as “ git add . “
Now check the status again , it converted into tracked or not.
Git status
-> git commit -m "first commit" all files & directories were committed to ready to
github.
git commit -m "first commit"
->type git branch -M main adding into the main branch (by default main branch exist
in github)
Figure 128. git branch
© Edunet Foundation. All rights reserved. | 401
type git remote add origin https://github.com/ajay4ugit/CRUD_NEW.git for trying
to connect into GitHub repository.
Figure 129. git remote
finally, we are pushing entire MERN project (frontend + backend) to github.
Figure 130. push MERN project to github
Now we are refresh the project and check MERN Project added into the github or not.
© Edunet Foundation. All rights reserved. | 402
Figure 131. Project Added in Repo
2. Create account in rendor.com(deploy)
Type https://render.com/ in browser to connect rendor page.
Click on dashboard to register through github.
(note: github with Repository is required)
Figure 132. Create an Account in rendor.com
© Edunet Foundation. All rights reserved. | 403
Figure 133. Render Signup
click on the GitHub tab and enter credentials to enter into the render page.
Figure 134. Render Dashboard
© Edunet Foundation. All rights reserved. | 404
3. Deploy the first backend application project
click on a new tab and select the second option as “Web Service”
Figure 135. Github connect Render
click on again github button and select radio button as only select repositories.
Figure 136. Option install render
select our repository and click on install button to install
© Edunet Foundation. All rights reserved. | 405
Figure 137. Click on Install
select GitProvider tab and select our repository and then click on connect button
Figure 138. Click on connect
Enter name of the backend and enter root & build and start command, follow same
as the given below picture.
© Edunet Foundation. All rights reserved. | 406
Figure 139. name Backend
select Free from instance Type.
Figure 140. Select Instance Type
->select Add from .env file
Figure 141. Add .env File
->Copy the data from the .env file from backend directory and paste inside of .env
box here.
© Edunet Foundation. All rights reserved. | 407
Figure 142. Copy .env File
click on the Add Variables button & finally click on Deploy Web Service button
Figure 143. Delpoy Web service
Now find our backend project deployed or not
Figure 144. check backend deployed
© Edunet Foundation. All rights reserved. | 408
Finally, our backend application is successfully deployed on Render site.
4. Add backend successful deploy URL in frontend code
The below picture exist successful deploy URL link.
https://crud-new-backend.onrender.com
Figure 145. Deploy URL link
goto frontend project and change url in Add.jsx
Figure 146. Change URL in Add.jsx
© Edunet Foundation. All rights reserved. | 409
change url in User.jsx
Figure 147. Change URL in User.jsx
change url in Edit.jsx file
Figure 148. Change URL in Edit.jsx
now update changes need to push into the github repository again.
© Edunet Foundation. All rights reserved. | 410
5. Deploy frontend application project into Rendor.com
Click on new and select second option as Web Service from Rendor.com
Figure 149. select web service
select our repository and click on connect button
Figure 150. click your repo connect
enter following frontend details as given below
© Edunet Foundation. All rights reserved. | 411
Figure 151.enter frontend details
finally , click on Deploy Web Service
Figure 152. Deploy web service
6. Check frontend URL in the browser is working or not.
Figure 153. check frontend url result
© Edunet Foundation. All rights reserved. | 412
After frontend project service is live and check both frontend and backend status is in
Deployed mode.
Figure 154. Frontend Project Live
Copy CRUD_NEW_frontend URL
https://crud-new-frontend.onrender.com
check on the browser
© Edunet Foundation. All rights reserved. | 413