WebDev Angela Udemy Notes

Download as pdf or txt
Download as pdf or txt
You are on page 1of 60

Introduction

When you type a URL in the browser, it needs to map it to the IP address of that URL.

1. Computer: Use its own cache — If not found, move to step 2.


2. Name Resolving Server: Checks Name Resolving Server Cache — If not found, move to step
3. (The Name Resolving Server is the ISP - Internet Service Provider)
3. Root Server: Get the Top Level Domain server IP address and tell the Name Resolving
Server — Got TLD Server Address. Move to step 4.
4. TLD Server: Get the .com Domain Server IP address and give it to Name Resolving Server.
Move to Step 5.
5. .com Domain Server: Got http://whizlabs.com server IP address. Pass this to Name
Resolving Server and cache it. Pass this to the computer and cache it.

[ Client, ISP, TLD, DNS ]

Browser - software that allows you to look up IP addresses, and receive data.

HTML

For documentation
https://devdocs.io/

- An inline element cannot contain a block element.


- each < > in html has an HTML element (like h1, hr, br : tag name) followed by an HTML
Attribute.
- each html element has global attributes (such as class, id)
- HTML boilerplate gives you a basic code template of html, just type 'html' in vscode and press
enter
- <!DOCTYPE html> is not an html tag. It's information to the browser about what type of file to
expect, here html.
- <em> </em> : for emphasis to text (em and i both italicize)
- <strong> </strong> : both strong and b make text bold
- ol(ordered list), ul(unordered list), li(list item)
- <a> anchor tag has href as the most imp html attribute
- table, thead, tbody, tr, th, td
- form, label, input (input has an html attribute called 'type' which could be text, submit, etc)
- the form in html has the attribute called 'action' which takes the url for what to render. Even the
href of anchor tag takes url. This could be relative to the code, ex- 'index.html', or a url
'http://google.com', or a mail sender which is written as 'mailto:[email protected]'

CSS

Website to find good colors and their codes: https://colorhunt.co/palettes/trendy

- Everything in css is just a box, and we use the chrome extension 'Pesticide' to debug css code
- <link rel="stylesheet" href="style.css" /> is to be done in head tag of html to link them
- note that the link you make to the external css style sheet must me in the head section of the
html
- anatomy of css: selector { property : value ; } , example: h1{ background-color: blue; }
- 'tag selectors' are h1, body, img, etc
- 'class selectors' start with a '.', written as .class_name
- 'id selectors' start with a '#', written as #id_name
- difference between id and class: id can be used only for 1 element, whereas class can be
used for many together, AND , an html element can have only 1 id, whereas there can be
multiple classes
- valid: <h1 id="name1"> </h1>
- invalid: <h1 id="name1 name2"> </h1>
- valid: <h1 class="name1 name2" id="name3"> </h1>
- hover in css is a pseudo class written as :hover along with the html element (tag, class, id) that
you want to change hover properties of (let's you define the state of the css element).
- example: h1:hover{ … } , so this style is applied only when you hover over the h1 heading

Intermediate CSS

- Favicons: they also need to be linked in the 'link' tag in the head of the html.
- <head> <link ref="icon" href="css/fav_img.ico> </head>
- div is a content division element, and is used to group/divide the content on your website into
boxes.
- border-width, to specify, it follows the order: top, right, bottom, left
- the Box model of website styling
- each html element has this box model, which can be viewed in chrome developer tools
(inspect element). In the elements part of this tools, select the element like h1, div, etc, and the
corresponding box of that element shows up in the styles
- each Box has margin, border, padding and the content block
- Box Model has: Margin, Border, Padding
- The 'Display' property of css has 4 different values:
1. Block
2. Inline
3. Inline-Block
4. None
- Block elements take whole width of the screen
- Common block elements: paragraphs, headers, divisions, lists, list items, forms
- Common inline elements: spans, images, anchors
- we can change the 'display' property in css to make the element 'inline-block'. This means that
it allows multiple elements on the same line, as well as allowing us to change the widths of
these elements. [ display: inline-block; ]
- display: none; makes the element disappear. The other way to make an element disappear
from screen is to change the visibility option: visibility: none;

- The 'Position' property of css has:


1. Static
2. Relative
3. Absolute
4. Fixed
- The 4 Coordinate properties are top, right, bottom, left.
- When position is set to 'relative', it does not affect the positioning of any other element in the
screen.
- Relative vs Absolute positioning: relative positioning is relative to the default position where it
should have been and it provides the coordinate wrt that. For ex, {position: relative; right: 20px;}
will move the image leftward by 20px wrt its default position.
Absolute position is wrt the parent element, and hence it moves the image rightward by 20px wrt
its default position.
- relative: relative to the original position where it should have been
- absolute: relative to its parent container
- fixed: this element is fixed to its position, and never changes its position even when you scroll
down. For ex, it's used in the nav bars (that are always on the top, even when you scroll)

- To center align text, we first do 'text-align: center' for the body tag
- for other elements like h1, if you specify its width as 20%, now to centre align this block, you
need to specify the 'margin' property as ' margin: 0 auto 0 auto; '. The left and right must be auto
so it adjusts automatically to centre align that block of width 20%

- static: Default value. Elements render in order, as they appear in the document flow
- absolute: The element is positioned relative to its first positioned (not static) ancestor element -
- fixed: The element is positioned relative to the browser window
- relative: The element is positioned relative to its normal position, so "left:20px" adds 20 pixels
to the element's LEFT position
- static is the default position property used by css
- we can embed 'fonts' from google fonts by including them in the link
- to get icons and images: www.flaticon.com
- to get giphs: www.giphy.com
- font-size uses units such as: em, px, %, rem
- 1em = 16px = 100%
- rem is 'ripped em', which rips of all parent font sizes (and does not add them like em does)
- suggestion: use 'rem', out of all those

- float property: is used to wrap around text, for ex to display an image on the left followed by
text on the right (instead of having it on different lines)
- the 'clear' property acts as the opposite of the 'float' property.

Bootstrap

- Bootstrap is a front-end library


- Bootstrap helps make your website 'Responsive', and hence adjustable.
- CDN (Content Delivery Network) is a group of servers that work together to provide fast
delivery to internet content.
- Bootstrap makes your website responsive, and hence responds to the sizes and adjusts
accordingly.
- buttons, carousels, cards
- to align multiple things in one row using bootstrap, we use classes like 'col-md-4', 'col-lg-6'
- the z-index is a property which allows you to specify which element sits on top of the other, i.e.
its relative distances to the screen and from the user.
- By default, the z-index of every element is 0, and a positive index means closer to the user,
and negative means away from the user.
- z-index does not work when the position property is static, which is the default property. It
works with all the other position properties which are absolute, relative, etc.
- css media query viewpoints : Media query is a CSS technique introduced in CSS3. It uses
the @media rule to include a block of CSS properties only if a certain condition is true.
- @media <type> <feature>
- you can do a lot of the responsiveness using bootstrap, but these css media queries allow you
to specify these break points additionally to be a little more specific on the responsiveness.

- there are two types of html tags: semantic and non-semantic


- semantic tags convey meaning like: <section>, <nav>, <table>
- non-semantic don't convey any meaning, they are more generic: <div>, <span>
- for icons, use font awesome, you can change their colors also and style them
- for anchor tags to refer other sections of the same page, give the section a unique id, for
example id="contact-sec", and then in the anchor tag of section, for href's reference, you can
just mention href="#contact-sec"

Web Design

- The 4 principles of Web Design are:


1. Color Theory
2. Typography
3. User Interface Design
4. User Experience Design
- there are 2 main font families: serif and sans-serif
- sans-serif is when you want to appear more authoritative
- serif is when you want to appear more friendly
- Keep in mind 5 things while designing
1. Hierarchy
2. Layout
3. Alignment
4. White Space
5. Audience
- use canva.com to build websites and their layouts and play around with ui, ux

JavaScript
- JavaScript is a scripting language, it tells the html elements to behave a certain way, just like a
script for a movie tells the actors to do what and when.
- JS controls the web
- JavaScript is an interpreted programming language, whereas Java is a compiled programming
language
- Inspect element -> Sources -> add index.js file : to add js on to the chrome browser
- Whereas a console is usually used to check line by line code, by testing it there.
- Most programmers use the console as a tool to help them “debug” (i.e., investigate and fix
problems in) their code, but you can also use the console as a way to just play around with
JavaScript
- alert("your message"); : alert is a function
- prompt is similar to alert, but it takes an input from the user.
- var name = prompt("Enter name: ");
alert("Hello " + name);
- camelCasing is used in JS mostly
- strings: concatenation(using + symbol) , string slicing,
- string has functions and attributes such as s.length, s.slice() (just like in python we do s[ : ])
, s.toUpperCase()
- var, function
- Math.round(x), Math.random(), Math.floor(x)
- === is equal to, !== is not equal to
- difference between var, let , const:
● const x = 10, now u can't change the value of x
● let x = 10, you can do x = 20, but you cannot do let x = 20 (cannot redeclare variable x)
● var x = 10, you can do both x = 20 and var x = 20.
● var declares the variable to be in global scope, whereas const and let define in block's
scope
● we generally use let and const (and don't prefer var)
- Math.random() generates a number between 0 and 1, and it's a floating number
- Google Chrome has an embedded JavaScript engine that runs all the basic commands,
hence we use inspect element and console to check our javascript.

DOM
- inline javascript: <body onload="alert('Hello');" >
- internal javascript: <script type="text/javascript"> alert("hello"); </script>
include this line in the body, at the bottom
- external js: <script src="index.js" charset="utf-8"> </script>
- Browser reads the html file from top to bottom, hence we put the css in the head, and the js in
the end of the body after all the html body elements
- The task of converting an html file to a DOM (Document Object Model) is done by the browser,
when you load up the webpage.
- document.firstElementChild.firstElementChild : gives the 'head' section of the webpage
- document.firstElementChild is the 'html'
- document.firstElementChild.lastElementChild is the 'body' section of the webpage.
- so the objects inside DOM can have properties and methods.
- document.querySelector("h1") allows you to select all the h1 in the DOM,
document.querySelector(".class_name") allows you to select all the classes with this name.
- hence querySelector allows you to select specific parts of the document DOM.
- The querySelector() method only returns the first element that matches the specified
selectors. To return all the matches, use the querySelectorAll() method instead.
- Changing HTML elements:
● element.innerHTML = new html content: Change the inner HTML of an element
example: changing the h1 tag name to something else
● element.attribute = new value : Change the attribute value of an HTML element
example: .src attribute of an image
● element.style.property = new style : Change the style of an HTML element
to change the css properties
- Finding HTML elements:
● document.getElementById(id) Find an element by element id
● document.getElementsByTagName(name) Find elements by tag name
● document.getElementsByClassName(name) Find elements by class name
● document.querySelector() : this allows you to select elements the way you do in
css, example: #title for an id, .cards for class, and you can also specify multiple
combination of selectors like you do in css (for hierarchy of specifying one element)
- note that getElementById() returns a single element, whereas getElementsByTagName() and
getElementsByClassName() returns an array.

- to change the css properties using javascript, we use .style.property , but note that the
property names are camelCased in javascript.
so in css if we have font-size or background-color, in js we have fontSize and backgroundColor.
- document.querySelector("h1").style.fontSize = "20rem";
- in javascript, the values you set these style properties to must be specified in strings. Like
above, "20rem", and not just 20rem.
(unlike in css where you did not need strings)
- document.querySelector("button").classList : returns the list of classes that this html item
has. The returned list is of type DOMTokenList
- To add elements to the DOMTokenList, we use the 'add' method, and to remove, we do
'remove'.
- To change the text in the html using JavaScript:
● document.querySelector("h1").textContent = "<em> Good </em>";
this makes the h1 heading to <em> Good </em>
● document.querySelector("h1").innerHTML = "<em> Good </em>";
this makes the h1 heading to Good
so .textContent only modifies the text content between the tags, whereas the innerHTML also
allows you to change the html tags etc as it accepts the entire html code as the string.

- document.querySelector("a").getAttribute("href");
- document.querySelector("a").setAttribute("href", "www.google.com");

Followed by document.querySelector("X"), we do these:


● To change text: innerHTML, textContent
● To change styles: classList (and add a class which has css style defined)
● To add/change attributes of html tags: setAttribute
● To add events: addEventListener

- document.querySelector("button").addEventListener("click", func_name);
- note that the second argument of the addEventListener() method is just the name of the
function. Hence we don't call the function there as func_name(), we only mention name
- you can debug in chrome developer tools using 'debugger;'
- write debugger; followed by the function you want to debug, and it will run through each step
and display along the way.
- breakpoint is an intentional stopping or pausing place in a program, put in place for debugging
purposes.
- callbacks in javascript are used to pass one function into another function in js. In javascript,
functions are objects, and objects can be passed to functions as arguments.
- let myAudio = new Audio("drums.mp3"); will create a new html media element, and store it in
myAudio. Then to play the audio, you can do myAudio.play()
- inside the eventListener, the keyword 'this' helps us refer to the object that triggered the event.

- Objects are variables too. But objects can contain many values. The values are written as
name : value pairs (name and value separated by a colon).
- var person = {firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"};
- objects in js are created using similar syntax to dictionaries in python.

- To create multiple objects of the same type, we use a Constructor Function.


- The name of the Constructor function needs to have the first letter capitalized too. (convention)
- We can initialize objects using this constructor function.

- function BellBoy(name, age, hotels){


this.name = name;
this.age = age;
this.hotels = hotels;
}
bellBoy1 = new BellBoy("Aman", 27, ["hotel1", "hotel2"]);

- the only difference between calling constructor function vs any other function, is that
constructor function uses the word 'new' to create new objects, and that its name's first letter is
capitalized.

- to detect key presses in javascript:


document.addEventListener("keydown", function(event){
console.log(event.key);
});
- we added an event listener to the document, and also passed 'event' variable to the function,
whose attribute .key is used to get the key actually pressed by the keyboard.
- arrow functions (=>) provides another way to write functions.

- Higher Order functions are those functions that can take functions as inputs.
- x.addEventListener("click", function(event){
console.log(event);
});
- the above log would print MouseEvent, which was the event that triggered this event listener.
- Hoisting in javascript means that the vars and functions are hoisted to the top of the js file.
This means that even if you have declared and defined the function below/after calling it, it
would not give an error since the declaration has been hoisted to the topmost/first, hence it will
not feel like it has not been defined yet.

- setTimeout() method allows you to execute a function after certain amount of time has passed
- setTimeout(function(){console.log("now")}, 2000); is correct
- setTimeout(console.log("now"), 2000); is wrong
- this is because the function() should not be called in the declaration itself, hence we should
only give the name of the function as the second argument, and not call it instead.
- The most popular OOPs model is class-based. But javascript isn't class-based, it is
prototype-based.

jQuery

- jQuery is a javascript library.


- like we had Bootstrap which was a library that helped us simplify our struggles with css
mainly(and js too), jquery is a library that mainly focuses on simplifying javascript code.
- document.querySelector("h1"); can be shortened to jQuery("h1") and further to $("h1");
- To be able to use the jQuery library, we use CDN(Content Delivery Networks) , just like we did
for bootstrap.
- Note it is important to place the jQuery script tag just above the javascript script tag, and not
below.
- document.querySelector("h1") -------> jQuery("h1") -------> $("h1")
- the same thing works with .querySelectorAll() as well
- to this $("h1"), we apply the .css method to the jQuery(), so with this method (the .css()
method), if you have a single parameter of the property, it returns the values of that. if u have 2
parameter, you can change that css property to the second parameter passed,
- $("h1").css("color") : this returns the color of the h1 tag
- $("h1").css("color", "green") : this changes the color of the h1 tag to green color
- another method in jQuery is the addClass() method which works similar to what
.classList.add() would do
- hence always prefer .addClass() over .css() method since we always want to separate our
behavior (the js part) from the styles (the css part).
- similarly .removeClass() in jQuery(), and .hasClass() to check if it has a particular class or not
- so $(selector) by default selects ALL the elements that match that selector in the html
- To modify text using jQuery:
● like innerHTML in js, here we do $("h1").html("<b> new updated text <b> ");
● like textcontent in js, here we do $("h1").text("new updated text");

- To manipulate attributes using jQuery, we use the .attr() method


● $("img").attr("src") : this returns the src value
● $("img").attr("src", "images/dog.png") : this updates the src value to this new source
- To add event listeners in jQuery, we just need to do it as:
● $("button").click(function(){
$("h1").css("color", "red");
});
Note: this will get applied to ALL of the buttons and all of the headings on your
webpage, whereas if you wanted to do this using vanilla javascript, you would have to
use a for loop with querySelectorAll()
● Similarly we can detect other event listeners like .keypress()
● $(document).keypress(function(event){
console.log(event.key);
$("h1").text(event.key);
});
This is an example
- A more flexible way to add event listeners is using .on(), which similar to js takes 2 arguments,
the event listener, and the function to execute upon listening to that event

- Using jQuery to create html elements dynamically:


● $("h1").before("<button> New </button>");
using .before() you can add/create an html element and add it right before the h1 tag
● Similarly, you have .after(), and also .prepend() and .append()
- Difference between .before() and .prepend() is that before will put it just before that element,
whereas prepend will put it inside of that element and just before all the contents inside it.
- We also have something like $("buttons").remove() to remove all the buttons in your webpage

Animations in jQuery
- .show(), .hide(), .toggle(), fadeIn(), fadeOut(), fadeToggle(), slideUp(), slideDown(),
slideToggle()
- This .slideUp() and .slideDown() can be very useful when you deal with drop down lists.
- jQuery also allows you to do custom animation using the .animate() method, like this:
- $("h1").animate({margin : 20rem }); this will gradually change the margin to this value,
note that you can only change numeric properties in this animate method
- you can chain multiple of these animations together,
$("button").on("click", function(){
$("h1").slideUp().slideDown().animate({opacity : 0.2});
});
- Inside the handler, you can use the keyword this to refer to the button object that triggered the
click. So sometimes you use the 'this' object, whereas sometimes you use the 'event' which we
pass as the argument to the function.

Resolving Git Conflicts


- if you have some changes in the github repo, which don't reflect locally in your machine, and
you also have some changes locally which are not pushed yet; this causes a conflict. To resolve
this conflict we use 'git pull --rebase' which pulls the github content to your local machine, and
then you can do git push.
- Another way is to use stash, note you can stash only uncommitted changes. So do
git stash save my_temp
Then do your pull, and then to get back from the stashed changes, do
git stash pop
After this you can add/commit and then eventually push

Backend Web Development

- Backend technologies used commonly are: php, nodejs, java, ruby


- Frameworks to assist these are: cake php, express js, spring, ruby on rails
- other backend stuff u can use include asp.net, python

Nodejs
- Nodejs allows us to use javascript for our backend too.
- Websites such as Netflix, Uber, Twitter all use node js.
- Node Js allows us to take js out of just the browser, liberating it to interact with the hardware of
the computer (and not just be trapped with the browser like how we saw till now for front end
javascript)
- So nodejs allows you to run and execute javascript code on the server
- In the terminal we write 'node index.js' , this command means that we use node to execute
the file index.js. And the contents of the index.js which are inside console.log() will get logged to
your terminal.
- Node REPL(Read Evaluate Print Loop) allows you to write line by line js code and execute it
each time you press enter, very similar to the chrome developer tools interface you did in that
console.
- so to use node repl, just type 'node' in the terminal, and then you can execute javascript
commands line by line.
- The 'fs' module provides an API for interacting with the file system, and whenever you need to
use a node module, you write 'require' in your js file.
- fs.copyFileSync(src_file_name, dest_file_name);
- builtin require function is the easiest way to include modules that exist in separate files. The
basic functionality of require is that it reads a JavaScript file, executes the file, and then
proceeds to return the exports object.
- hence this require() function allows you to import/use other modules (pieces of code), that
exist in separate files. But to use pieces of code that other people would have written that's not
in these modules that you get when you install node, we use npm
- so node is a runtime environment that allows you to run and execute javascript code outside of
the browser, and in your local machines and on servers.
- npm is: node package module.
- to initialize your own package do 'npm init' in the terminal, and this creates a package.json
file in that folder which is a json file with metadata.
- The other important aspect of a package.json is that it contains a collection of any given
project's dependencies. These dependencies are the modules that the project relies on to
function properly.
- By running an install command (npm install) inside of a project, you can install all of the
dependencies that are listed in the project's package.json

- npm install <module> In this command, you'd replace <module> with the name of the
module you want to install. For example, if you want to install Express (the most used and most
well known Node.js web framework), you could run the following command:
npm install express The above command will install the express module into /node_modules
in the current directory.
- Whenever you install a module from npm, it will be installed into the node_modules folder.
- the command 'npm install' will install all the dependencies listed in the package.json file of that
directory, whereas the command 'npm install express' will install the node module called
express.
- so package.json is a description of all the packages so far ( and the dependencies )
- so whenever you install something using 'npm install <module name> ' , the "dependencies"
field is added to the json file which now contains this module as a dependency.
- We previously did 'require("fs")' which was using an internal nodejs module, and now after we
installed a module express, we can now 'require' it in the same way we did for the other node
module such as "fs".

Express
- Express is a node framework
- Like jQuery is to javascript, similarly express is to node.
- so express is a framework, or a bunch of code that someone else wrote, that adds extra
features and helps to organize and structure your code.
- Express was built to help you write less repetitive code when you're building web applications,
and is made specifically for web developers.

- To create a real server locally on our computer using nodejs and express.
- to use the keyword const for 'const express = require("express")', we need to write a hint to the
linter as //jshint esversion:6
- const app = express(); : this is a function that represents the express module, and we bind
that to the word 'app'.

- app.listen() : listen is a method which tells it to listen to this port where any http requests get
sent to our server. A port is basically just a channel we tune our server to.
- In every home, there is one mailbox and multiple people. The mailbox is a host. Your own
home mailbox is a localhost. Each person in a home has a room. All letters for that person are
sent to his room, hence the room number is a port.
- Just as the IP address identifies the computer (on the TCP/IP network), The network port
identifies the application or service running on the computer.
- so, ports allow different applications to run on the same machine (each listening) at different
ports.
- Socket is a combination of IP address and port. [ socket = IP address + port ]
- Ports are a way of uniquely identifying each application on that machine. Hence when we
make a request (here we are clients), to the server of google.com, it goes to the corresponding
IP address(which it obtains from DNS), and then to access 'which' application on their server,
the port number also needs to be specified (which in most web application cases will be 8080).
- When we do app.listen(3000) we are asking the server to listen at the port number 3000. To
see what it is listening, we can use applications such as 'telnet' or the 'chrome browser', which
are also clients which will send requests to this port and give us information of what is going on.
Multiple clients can talk to the server at once.
- Now to get our server up and running, we write app.listen(3000) in the js file. Once we run this
file, we have a server up which is listening on this port 3000. Now, to check if it is listening
properly, we can use 'telnet' by opening another terminal window and the command
'telnet localhost 3000' which connects to the local host at this port number.
To do the same thing using the chrome browser application, type 'localhost:3000' in the bar, and
it allows to analyse the same thing (just like telnet is an application that connect to the 3000
port)
- so note that, when we ran 'node server.js', we got the server running because of the line
app.listen() in the server.js file. Now, once the server is up and listening, we need to be able to
connect to our server through an application, which here is the chrome browser where we
specify localhost:3000 (this can be done using the telnet application too, using the command
telnet localhost 300, which allows us to do the same thing through the terminal)
- now we need to write code so that after we make the port listen, we need to handle what it
does after a client connects to it, what response it will send for what type of requests.
- app.get() is a method provided by express which allows us to specify what should happen
when a browser/client gets in touch with our server and makes a get request.
- "/" means that the request is being sent to the root of the website/server.

- A callback is a function that is passed into another function as an argument to be executed


later. ex-
app.get("/", function(request, response){
response.send("<h1> Hello world! </h1>");
});
Here, the second argument to the .get() function is a callback function, which is a function
passed to .get() function, and it gets called only when the get request is made at the "/"
endpoint. So the first argument here is the route at which we want this response to be sent for
(here it's the home route "/").
- So app.get() handles what should happen when a user sends a get request to the server. The
first argument is the route which we are specifying the get request to. And the second argument
is the callback function which gets triggered when a get request is made to this endpoint. This
function takes two arguments request and response (you can name them anything, but this is
the convention).

- so, app.get("/", function(req, res){


});
In this method, we specify the route as the first argument which here is "/", and the second
argument is the callback function which is called when a get request is made to this route "/".
"/" is called the home route (the default route)
"/contact" is the contacts route.

- A URI (Uniform Resource Identifier) is a sequence of characters that identifies a web resource
by location, name, or both in the World Wide Web.
- So when we use the chrome browser and specify the URI as 'http://localhost:3000/contact'
which means that we are using the chrome browser to make a request to the server listening at
port 3000, at the route '/contact'. Here, the chrome browser provides us the 'http client' which
sends a 'http request' to the server listening at port 3000. This 'request' can be get/post/
anything else, and this is interpreted by the browser here and sent as a http request to the
client. Then this function() of ours as the second argument handles and responds to the request
accordingly.
- Note: ^C (Ctrl + C) kills the server, whereas ^Z only stops the server (it does not kill it, which
means its still listening at that port, and hence the next time you do node server.js, it gives an
error that someone else is already listening at that port).
Hence always do ^C to kill servers (and not ^Z)
- If you did ^Z by mistake, then to get back the process to kill it, type in the terminal 'fg' which
brings up the jobs currently running in foreground. Then you can do ^C after that. To see all the
running jobs at the moment, write in the terminal 'jobs'.
The jobs command displays the status of jobs started in the current terminal window
- Everytime we make changes in the code, we need to save the .js file, bring down the server,
and then rerun the server each time. To avoid this, we use 'nodemon', so instead of doing 'node
server.js', we instead run 'nodemon server.js'. So everytime we save the .js file, nodemon
restarts the server automatically
Hence, use 'nodemon server.js' to run the .js file and to make the server listen to that port
continuously.
- Till now we saw the .send() api provided by express, now to send an entire file as a response,
we use the .sendFile() api. This method takes the path of the file you want to render which in
our case is the index.html file.
- If you just do response.sendFile("index.html"), this will work now since the server is hosted on
my local machine itself. But when you deploy it later, it will be hosted on the cloud (someone
else's computer), so the files absolute path will change and this won't work. So, we shall specify
full path correctly using __dirname which gives the current directories path
=> response.sendFile(__dirname + "/index.html");

- HTTP return code:


1** (100s range): Hold on, somethings going to happen
2** (200s range): Here you go, its a successful request
3** (300s range): Go away, redirect
4** (400s range): You screwed up
5** (500s range): I screwed up
- some of the common http return codes are 200: successful request, and 4** which are the
client errors(for example the user is asking the browser to request something that doesn't exist).

- To be able to deal with the data posted by users using the html forms, we need to use another
node module which is 'body-parser' (just like we installed the express module). So just do 'npm
install body-parser', and then it comes as a dependency in your package.json file. Now just
require() it in your .js file.
- So to use body parser, do app.use(bodyParser.urlencoded({extended : true}));
- we use .urlencoded() whenever we are dealing with data collected from forms.
- now inside the callback function of the post method, we can use request.body to access all
contents obtained from the form. If the name field in the form was num1, then we access it as
request.body.num1
- the 'action' field in the 'form' specifies where it would submit the form, in our case "/", hence it
submits to this route, and hence the post method for this route will handle this case.
- note that request.body.num1 is a text field, and if you want to convert it to a number, just do
Number( request.body.num1 );
- Note that this code is running on the backend, the server side, and the client/browser knows
about none of this.
APIs
- APIs (Application Programming Interfaces) is a set of commands, functions, protocols and
objects that programmers can use to create software or interact with an external system.
- we have used jQuery APIs which were methods provided by jquery such as .add(), etc which
made our code writing much shorter and smaller. Hence these are also APIs (as they allow
programmers to use them to create software).
- Tinder uses facebook's APIs to show information like 'shared' friends, etc. This is 'interacting
with an external system'.
- Here, we focus on APIs that allow us to interact with an external system (most importantly, an
external server). So the external system has exposed APIs, using which we request data from
their servers.
- So API is like a menu which tells you about what are all the things you can do with their
services. And to be able to interact with their data, we need to use these APIs which they
exposed, like a weather website which exposes APIs about weather forecast to get temp, etc.

- When using APIs, there are 4 things we need to care about:


● Endpoint
● Paths
● Parameters
● Authentication

- API Endpoint is one end of the communication channel.


- In web dev and in what we are learning here, we make API calls from the chrome browser, and
we mention the website/url with the endpoints specified (like www.iris.com/login), so this /login
is the endpoint which helps identify which service on that server (of iris) i'm sending my get
request to. And as a response, the iris server sends the html page which my browser renders.
(So this is basically the type of APIs we deal with when dealing with web applications.
- These APIs that you access on the internet through a web browser and all are REST APIs.
It is commonly used to create interactive applications that use Web services. A Web service that
follows these guidelines is called RESTful.

- https://sv443.net/jokeapi/v2/
checkout this website for jokes, and it provides joke APIs to get a random joke.
- So when I make this API call: https://v2.jokeapi.dev/joke/Any?format=txt&type=single
So this is the exact URL at which we are sending our request (from the chrome browser since
we put this url in the chrome tab). Here, the endpoint is the part till 'https://v2.jokeapi.dev/joke'.
- But we need to specify a specific path after the endpoint, here '/Any', where /Any is the route,
and this API endpoint specifies exactly from where it will get data from that server. So, here we
are making a get request.
- So here, the endpoint is: https://v2.jokeapi.dev/joke
- And to complete the path of the url, we need to specify: '/Any'
- So the Path here is: https://v2.jokeapi.dev/joke/Any
- To allow the API to be flexible to deal with flexible queries, APIs allow you to provide
parameters. The URL Parameters go at the end of the url after a question mark '?'. And these
parameters are specified by a key-value pair separated by an '=' equal to sign.
- https://v2.jokeapi.dev/joke/Any?format=txt&type=single
So after the '?', we specified the parameters, that we want format to be equal to txt, and the type
to be equal to single. So to specify more than one parameter, each parameter is separated by &
symbol.
- So, through the use of paths and parameters, we are able to specify the API more specifically.
All these parameters are basically for the 'get' request which we are requesting from the joke api
server. (Note: this is still a get request, and not a post request).
- So these formatted URLs allow us to make these API requests to those servers easily from our
browsers.

- Authentication
Through the API, they (the servers / api providers) have to be able to identify you as the
developer and they have to keep track of how often you are using their server to get data, and
then charge you or limit you accordingly.
- The weather APIs website is: https://home.openweathermap.org/
- When we sign up, we get a unique API key, which is an id that the server uses to uniquely
identify you, and keep track of how many requests you are making
- The format to make API calls to this weather server is:
api.openweathermap.org/data/2.5/weather?q={city}&appid={API key}
Here it takes 2 parameters which are city name and the API key provided when you had signed
up.
- Also, to understand how the same url shows your account / another person's account for them.
This is done using cookies. So, the first time you sign up, a cookie (for ex in the format of a jwt
token will be sent to you/client from the server), which will be used to uniquely identify you the
next time you make any requests to the server. So basically, the next time when you make a
request to the server, the cookies are also sent as part of the request which the server uses to
identify (by verifying the cookie/jwt token with what it had sent to you) that it is you who made
the request.
- Hence these cookies help you stay logged in, without having to re-login every single time.
- These APIs are returning the request in json format. To easily understand json format, we can
use chrome extensions that allow us to do so.
- The order of specifying parameters (separated by '&') does not matter.

- To kill all processes listening at port 3000:


lsof -ti tcp:3000 | xargs kill

Postman
- So far, we have tested APIs using the chrome browser by typing the whole url with specifying
the endpoints and the parameters. This can be prone to human errors while typing this whole url
out, since it's hard to see where each parameter ends and the new one begins.
- Hence, while testing out our APIs, we use a tool called Postman.
- So basically, just as our chrome browser is a http client, similarly postman is also an http client.
(that allows you to make these requests and api calls in a more visually formatted way)

Learnings from Networks, HTTP, TCP, IP


- We are using the HTTP network to send out 'packets' on the network (these packets in this
context are basically the get prequest we are making to the 'www.google.com' server).
- So this networking is hierarchical (and structured one on top of the other). The most basic one
is IP (which just sends packets from the client to the server, it sends it by sending from one
machine (IP address) to the next until it reaches the server it was intended to reach. This is
basically the IP part of it, which makes sure that your packet has reached the right IP address.
The TCP part adds additional functionality of making sure that the packet has successfully
reached (and if not it sends it again, so TCP adds a layer of security as well). And as we saw, IP
sends the packet to the desired IP address, and then the TCP is the one which sends it to the
correct port number on that IP address of the server. Then HTTP is the next layer on this
network, and it specifies the endpoints specifying what services you want to access on that
server at that port.
- Layered networks:
● IP : Helps packet reach the unique IP address on the network
● TCP : Helps packet reach the unique port on that IP address.
● HTTP : Helps the packet/request reach the correct endpoint to access the desired
services.
- Everything on this network has an IP address that identifies it uniquely. Even the router/modem
has a unique IP address. So my modem called 'Airtel-Study' has a unique IP address to which
all my requests are sent through the IP protocol, and the model sends my packet/request to the
'Airtel' (my service provider) which ultimately send it to the server's IP address to which I had
made a request to.
- Packet is basically a carrier for my request (which I send to the server).
- Postman also allows you to see the http request that it (as the client) is sending to the server,
along with the headers, etc.

JSON
- JSON is JavaScript Object Notation. It looks very similar to a javascript object, and hence this
name. The difference is that when you create an object in javascript, when you make the
key-value pairs, the keys are never strings, whereas in json, keys are always "strings".
- JSON format is extensively used to transport data over the internet, because it's very readable,
and it can be easily compressed to a string and transported, and then recompressed later at the
other end too.
- Other such formats are XML, HTML, JSON

- Now we want to make a project that displays the weather data using the weather APIs
provided by openweather.org website.
- So our structure flow looks like:

- So we need to be able to get data from this external server (here the weatherapi.org by using
their apis). To do this we use another node module called 'https'. The https node module is a
native node module hence doesn't have to be installed every time like we had to do for the
express module.
- Hence, we can use the https, a native module of node, to make get requests to external
websites (it performs a get request across the internet using the https protocol).
- The 200 (OK), 404 (Not found) are the HTTP Status Codes, and using this https module, we
can print them as, console.log(requestFromHttps.statusCode);
- Some common http status codes you'll come across are:
● 200 : OK, means that everything went find, and your request was made successfully
● 404 : Not Found Error, means that the path you specified is wrong since that url/endpoint
does not exist
● 401 : Access Unauthorized (unauthorized http request). This is the error you could face
when you entered the wrong API key, whenever you deal with such authentication using
servers.

- JSON provides two methods to compress and uncompress your data, which are:
● JSON.parse() : to uncompress the data, and returns a javascript object
● JSON.stringify() : to compress your javascript object to a string.
- We get hold of the data using the response.on("data", <callback function here>); using the
.on() method.
- The data we got was in hexadecimal format, hence we used JSON.parse() to convert it to a
javascript object.
- Note: You can have only 1 res.send() in any of the app.get() methods, else it will crash.
- So in order to be able to send multiple lines to the client as a response, we use
response.write() method. We can have multiple response.write("...your text…"), and eventually
just do 1 response.send();

- If you do .sendFile(__dirname + "/index.html"); this will show the html page, but it won't be
able to use the "style.css" or the images specified locally inside this because it doesn't have the
relative paths to those files.
- So to do this, make a new folder, let's call it "public". Now inside app.js, add the line (which is
express code to allow you to use these static files), app.use(express.static("public"));
- Now all the paths that you specify for static files (of images and css styles), you can specify
them wrt this folder "public".

- In the weather API project, we only sent a get request to the external server to retrieve data
from them (so we just used https.get()). But here, in the mailchimp project, we need to post data
to their servers, so we use https.request(url, options, function(){});

Here, the options field is an object which takes, method : "POST".


On getting a response, to use the response received from an external server using https, we
use response.on("data", callback_function()) method

const request = https.request(url, options, function(response){

response.on("data", function(data){
console.log(JSON.parse(data));
});
});
request.write(jsonData);
request.end();

To send data to the external servers, we just use request_name.write(), and then the .end()

- The data sent back by all these external servers using their APIs is usually binary/hexa when
you receive it in this 'data' field. Hence, always do JSON.parse(data), to convert it to a
javascript object, which we can use.

Deploying using Heroku


app.listen(process.env.PORT, function(){
});
- Locally we made it listen on port 3000, but when we deploy it on the heroku servers, this port
might not be free, hence we let heroku dynamically assign us a port by specifying
process.env.PORT.
This would not work locally anymore since this 'process' object is defined by heroku.

app.listen(process.env.PORT || 3000, function(){});


This will allow it to listen to port 3000 when run locally. Hence now our app would work both
locally and on heroku.

- The Procfile is the file that Heroku uses to know how to start our file. So inside the Procfile, we
specify the command it needs to execute to get our app running, which in our case should be,
web: node app.js
(Note that Procfile must be named exactly this, and not procfile or Procfile.txt, etc)

- So before deploying to heroku, remember to make the following changes in your project folder:
● In the app.js file, change the local port 3000 to: process.env.PORT || 3000
● Add the Procfile, and inside it write: web: node app.js
- Steps to deploy on your heroku after you have made an account on heroku: (In the terminal do
the following steps, very similar to what you would do for pushing code to github)
1. git init
2. git add .
3. git commit -m "first commit"
4. heroku create (this would create a link at which your website is hosted)
5. git push heroku master (very similar to how you would push code to github)
The next time you make changes, etc. you just have to follow the same steps starting from git
add . and then it will get updates on the live website too!

- My heroku app here : https://floating-crag-96243.herokuapp.com/


Git, Github and Version Control
- When we do 'git add', we are adding files to an intermediary stage called the staging area,
where you can pick and choose which files inside your working directory that you want to
commit.
- git status shows the untracked files which are the ones that are not in the staging area.
- git add will add the files to the staging area, and the files are now getting tracked.
- So on doing git add, the file is now in the staging area and ready to be committed.
- So on doing git commit, you have committed your changes. And then to view your commits
history, you can do: git log
- Doing 'git log' displays the commit which is uniquely identified by a hash, the time and author,
and also the commit message which you gave it.
- so 'git add' takes the files which are only in the working directory to the staging area.

- Working directory is the one where you first do git init to initialize your repository in that
working directory.
- Staging area is where you stage and add files before committing. Why have a staging Area,
and not directly commit to local repo? Because sometimes there might be certain files that you
don't want to commit (files that you don't want to track), so you stage them, hence you dont add
them, hence they are the untracked files.
- So the staging area is a good place for you to know what the file you want to ignore (untracked
files) and what are the files you want to track.
- To view changes in a file, use the command: git diff chapter3.txt
It shows the difference between the current file's contents and the latest committed files
contents, and shows the added and deleted contents in the file.
- git checkout chapter3.txt will rollback to the latest committed version of that file, hence it
brings back that version of the file which was at the last checkpoint when you had committed it.
- Now to push up your code to something like github, first make a new repository in github. Then
we execute the command:
git remote add origin https://github.com/geegatomar/Learning-Git-Angela.git
which basically pushed my locally committed changes to this remote repository on github. This
basically tells my git that I have created a remote repository somewhere on the internet and I
want to transfer all of my commits over there.
- the remote repository here, we have named it as 'origin'. We could have named it anything
else, but this is the standard convention to call it 'origin'.

- Then we execute the command: git push -u origin master


In this command we are pushing our commits from our local repository to our remote repository
which is called origin, using the 'u' flag or the 'u' option which basically links up your remote and
your local repository.
We push it towards the 'remote' which is called 'origin', and we push it to the branch called
'master'.
- So in the command : git push -u origin master ,
-u: The 'u' option/flag basically links up your local and remote repository.
origin: Name of your remote repository (which you kept/named in previous command)
master: Name of Branch
- The master branch is the default branch or the main branch of all your commits.
- After pushing to github, you can go to: Insights ---> Network , this will show you the
network graph. And as you hover over the graph, you can see who added those commits along
with the commit messages.
- To view all the commits made in github, go to Code ---> commits (just under the download
Code option). And clicking on the commits also shows you the versions and the changes made
in that commit.
- Hence, on doing git push, we have pushed our local folder of .git to our remote repository in
Github. And here we were making all our changes on the master branch.
- Use gitignore to prevent committing certain files and secretive information such as API keys to
your public github repo.
- So for gitignore, we basically don't want files having passwords, API keys, utility information,
etc to be pushed to our github repos.
- so we make a hidden file called .gitignore, and to view it in the terminal, do ls -a, to be able
to view hidden files as well.
- git rm --cached -r . : is the command used to remove all the files from the staging area. So
you can use this if you have added a secret file to your staging area, but you don't want to
commit it. So you execute this command, and then if you see your git status, you will find all the
files to be untracked.
Then to continue, add a .gitignore file, and then 'git add .' to add everything back again.

- git rm -r --cached .
Here, --cached tells it to remove those files from the staging area (it's currently cached in the
staging area).
And the -r option is to specify recursively, ie. to remove files and folders inside directories (it
recursively removes directories inside directories. Note that -r is rm's option, just like you do rm
-r to remove any folder from the terminal). If you don't want to rm all the cached files from the
staging area, you can specify the exact files. And when you specify the exact files, you would
not have to do -r (since it's not a directory that needs to be recursively removed).

- So, another way to do this would be using 'git restore' as (to unstage those files):
git restore --staged <file_name>
- If you have committed a file (ie. the file is now in the committed Local Repository stage), and
you want to go back to an older commit. Note that git commits are atomic (immutable entities),
so you will deal with the commit as a whole, you can't just choose to revert back one particular
file (this is an important concept to understand that git deals with commits as a whole, i.e.
commits are atomic in nature).
- So to go back to a previous commit (i.e restore back to one of your older commits), you first do
git log to see all the commits you have made till now, and then use 'git reset' to revert back the
state to a previous commit. To do git reset, you could either do:
git reset HEAD~1 , where you specify how many commits back you want to go.
For ex, if you want to go to the third last commit, you do: git reset HEAD~3
You could also do this using git reset <hash_key>
for example: git reset e364451ccb1f7e8feca9329da0270697b1527773
- And note that all the commits in between will then be lost after reverting back to this previous
commit.

- There's another thing called 'revert', in which you can revert a particular commit. So on doing
this, it reverts that commit by creating a new commit with these changes in it.
git revert <commit_id_also_called_the_hash>
Cloning

- To clone someone else's repository from Github to your local machine, just execute the
command
git clone <url_of_the_repo_to_clone>
- Then you have their repository locally, and if you do "git log", you can see all the history of
commits made by people.
Branching and Merging

- Multiple people might be working on different features of the project, and hence each of you
work on different branches, and you merge it with the main master branch only when you know
that all your changes are correct.

- To create a branch, just do: git branch <branch_name>


- To check all branches: git branch
( The asterisk * shows your current branch )
- To move to another branch: git checkout <branch_name>
- Now, as you commit in your respective branches, the 'git log' would look different in each
branch.

- The red thing here which is "origin/master" shows the latest branch that is committed to Github
- The 'HEAD->alien-plot' shows the latest commit I have made in the current branch.
- To merge another branch with my master branch:
● First go to the master branch, git checkout master
● Then merge the other branch, git merge alien-plot
- After merging, all those commits made on the other branch will now show up in the master
branch, and even the merging step is added as a commit.
-- Forking is different from cloning because,
In forking, we just create a copy of someone else's remote repository and bring that copy to our
github now. Then, to be able to work on that remote local repository (the copy, which is now
under my Github account), we need to clone it. And then we have it in our local machine (only
after cloning it), and then we can add/edit code. Then upon pushing this code, it goes to the
remote local repository of mine (the one that I cloned), and only if you make a pull request, only
then you will be able to add these changes from your forked Github repo to their original github
repo.

-- So, there are two options of getting someone else's remote repository to your local machine
for you to work on:

1. Directly Clone 2. Fork and then Clone

After cloning to your local machine, you We first fork the repo and obtain a copy of
directly push to that repo from which you that original repo in our Github account. Now,
cloned from. But, if you don't have access to we clone to our local machine after which we
that repository to push, then when you do 'git can add/edit code. Then we do 'push' to our
push', it will give an error. Github (which is a copy of the original
someone else's repo). Note: Here we are
able to push because we are pushing to our
own Github, to which we have access. After
this, from sending code from our Github
account to their Github account (from where
you had forked), we make a Pull Request.
This is called a Pull Request, because we are
making a request for them to pull and accept
our code. It's their repo and they have the
charge and control over this.
- So forking basically brings code/projects from someone else's Github account to your GitHub
account. To be able to edit and add to that code/project, you will have to anyway clone it, which
will bring the code to your local machine after which you are free to do whatever you want.
- Forking: Brings from someone else's Github to my Github
- Cloning: Brings from Github to my local machine.

- Forking is basically making a copy or duplicate of someone else's remote repository, and
putting it under your own Github account.
- So, if you are added as a collaborator under some project, then you have write access to the
project, so you can just directly clone and then push to this repo. But in most cases (when
dealing with Open Source projects), you won't have this access, so you first need to fork, and
then clone to your machine, then push to your Github, and then make a Pull Request to the
original remote repository on GitHub (from your Github account)

- Summary of most common Git commands:


EJS (Embedded JavaScript templating)

- This is a very standard way to begin your 'app.js' file with, hence you can always begin with
this template. (since you're most likely always going to use express and body-parser modules).

const express = require("express");


const bodyParser = require("body-parser");

const app = express();


app.use(bodyParser.urlencoded({extended : true}));

app.get("/", function(req, res){


res.send("Hello!");
});
app.listen("3000", function(){
console.log("Server is listening on port 3000.");
});

- We need templating (for our html files), when we need to create html files that have very
similar content.
- ejs is one of the most popular ones that node developers use.
- to install it, like any other node module, just do: npm install ejs
and then require() it inside your app.js file. And add this line to tell you app to use ejs.
app.set("view engine", "ejs");

- This line tells our app to use ejs as its view engine.
- We then use the res.render() method which uses the view engine that we set up above to
render a particular page.

res.render("index", {typeOfDay : "3", exactDayOfWeek : dayOfWeek});

- The first argument is the page you want to render. Here, it's the 'index.ejs' page. These .ejs
files must be in a folder called 'views' folder. The ejs view engine will look for these files in this
particular 'views' folder.
The 'view engine' by default looks in the 'views' folder for files to render. So all these .ejs files
which you want to render, must be in the 'views' folder.
- The second argument is a javascript object. The keys are the variables that you will use in the
index.ejs file. And the value is the value you want the .ejs file template to replace it with.
- The .ejs file is written exactly like an html file, except that you use the ejs syntax to use those
keys of the javascript object that res.render() gives.
The syntax for this ejs templating part is: <%= %>
<%= theJavascriptObjectsKeyName %>
So this acts as a marker for ejs, and tells it that this is where you have to place the particular
variable's value.
We put in the variable name that we want to replace that marker with.
And the ejs file will replace this key with its corresponding value. So, this in a way allows you to
send data from you app.js file to the html files (here, we are sending to the .ejs file which is
exactly like javascript, except for the additional functionality of <%= %> hence we use ejs for
templating our html files).

- To get current day of the week in js,


let today = new Date();
let currentDay = today.getDay();

- To use control statements in .ejs file, like using if-else statements, we use the scriptlet tag of
ejs, which is written like <% %>, must see official documentation for this information. So if you
define any logic in javascript, you will have to add these scriptlet tags around each of those
lines. You must add these on 'EACH' of the lines, as they work on a line by line basis.
<% for(var i = 0; i < itemList.length; i++){ %>
<li> <%= itemList[i] %></li>
<% } %>

So, we basically first write out our logic part (if, else, for) using javascript, and then for all the js
parts, we add scriptlet tags on each of the lines as enclosed between <% %>, and leave out the
html part, i.e. don't put any ejs scriptlets for the html lines as shown above here.

- Sometimes instead of writing your res.send() or res.sendFile() or res.render() again, you could
just redirect to another route by saying res.redirect("/");

Scope of Variables
- Scope of local variables (variables inside a function) is limited to that function.
- So in javascript, you can create variables using var, let, const.
- var and let behave slightly differently in terms of their scope:

var let const

inside a function local local local

outside a function global global global

inside if/else global local local

- Suggestion: Avoid var. Use only let and const.


- Now, when you try to apply css styles to this .ejs file directly by specifying
href="css/styles/css", it would give an error that it did not find this file. This is because our
express only serves up the main access point which we defined in the package.json which is
app.js file here, and the 'views' folder
- So, as a javascript developer, it's a common practice to make a folder called 'public', and
inside this public folder, we put all our css folders, images folders, and javascript (the ones that
would execute on the browser for the front end) folders.
And we can tell express to serve up this 'public' folder.
So we add a line of code in our app.js which tells express to serve up this public folder which
contains all of our static files.
app.use(express.static("public"));

- Make sure to create a folder with the name "public", into which you move all your css folders,
images folders, etc and all these static files.

- EJS allows you to create something called 'layouts' or 'partials'.


So inside the views folder, create files called 'header.ejs' and 'footer.ejs'. And then add the code
for header and footer to these files. And then to all the other files like about.ejs or contact.ejs,
just use ejs syntax to include from those header and footer files as:
<%- include("header"); -%>
<%- include("footer"); -%>
in the corresponding places where you want them to appear.
This makes it easy to create a large website with multiple web pages that have similar styles.

Node Module and Exports


- To refactor our code, we send out stuff that's not so related to the routings and logic to other .js
files. So we made a date.js file to do this job for us, but how do we export variables and values
outside of this function.
- So inside every .js file, we have access to something called a 'module', which we can require
into other files to be able run all the code that's inside this module's file.
const date = require(__dirname + "/date.js");
This just says that we are requiring this file called date.js, and since this is not a npm module
like express or body parser (instead this one is local to us), we need to specify the full path
name, as shown here.
So whenever I say require a certain module, it will go into that module (here it's the file date.js),
and it will run all of the code that's in that file.
- To export from this module, we can do module.exports which is a javascript object which
allows us to export data outside of this module to whichever file 'requires' it.
- So in the date.js file, we write
module.exports.getDate = getDate;
where getDate is defined as a function that returns the date string.
- Then in the app.js, after we required it, we can just call the function by doing 'date()' as here:
const date = require(__dirname + "/date.js");
console.log(date());
- And since module.exports is object, we can explore multiple things from this module by doing
- module.exports (remember the s) is a javascript object, and objects have properties and
methods associated with it.

- There are multiple ways of declaring a javascript function, one of which is declaring an
anonymous function and setting is equal to the variable with a name, ex:
var my_func = function(){
};
It's the same as doing
function my_func(){
}
- Also note that module.exports can also be shortened and written as just exports
- When we clone someone else's node repo, it will not contain the node_modules folder, as they
would have gitignored it. But all the dependencies would be mentioned in the package.json . So
after cloning, all you need to do it to run the command npm install
on the terminal and then npm will go through the package.json and install all those necessary
files that are required for this project.
- the command 'npm audit' tells you the vulnerabilities.

- To add multi-line input in html, we don't use 'input', instead we use something called 'textarea'
which we use for multi line input.
- Another way to loop around an array (without the for(var i = 0; i < arr.length; i++)...), is to use
the forEach() method in javascript.
- so, the forEach() javascript code will look like:
array.forEach(function(each_element){
console.log(each_element);
});

Express route parameters


- Express allows you to do something called route parameters, as part of routing in express.
app.get("/news/:my_topic", function(req, res){
console.log(req.params.my_topic);
});
- So we specify the route dynamically using the colon : , which gets replaced by whatever you
specify in the url.
- Hence, route parameters are named url segments that are used to capture the values
specified at their position in the url. So whatever is specified in the place of colon will get directly
passed inside the callback function of app.get() where you can use it as
req.params.the_name_you_gave_after_colon
- So the ': colon' here somewhat gives you a regex type of flexibility. (concept of regular
expressions)
- This helps us tap into that part of the url which we pre-specified as a parameter (starting with :
colon).
app.get("/post/:postName", function(req, res){
console.log(req.params.postName);
});
-

- While nodemon is running, to restart the server, type rs in the terminal while nodemon is
running.
- camelCase vs kebab-case
The two most used cases in javascript programming.

Lodash
- Something that developers use a lot with Node is called Lodash.
Lodash is simply a utility library that makes it easier to work with javascript inside your Node
apps.
- To require lodash, the convention is to use an underscore (a 'low dash _')
var _ = require("lodash");
- We use _.kebabCase();

Deep Copy vs Shallow Copy


In javascript, normal ways of assigning a variable to another will create a shallow copy.
So, var shallowCopyOfPost = post;
this creates a shallow copy, and when you modify the 'post', even the 'shallowCopyOfPost' will
get modified with the same changes reflected
- To create a deep copy, we use lodash's _.cloneDeep()
var deepCopyOfPost = _.cloneDeep(post);

Databases
- Depending on the type of data you want to store, and the structure of the data, you choose a
database over another.
- Two main types of databases
SQL (Structures Query Language) and NoSQL (Not only Structured Query Language)
- The most popular databases when working with Node are:
● For SQL: MySQL, PostgreSQL
● For NoSQL: mongoDB, redis
- NoSQL uses JSON objects to represent your data, whereas SQL uses tables. Hence SQL is
inflexible.
- NoSQL is more flexible and when your data structure is not predefined you can use this as
you're not bound to a particular structure, and can flexibly change it later very easily.
- SQL databases are very good at keeping relationships in your database, hence called
relational dbs, whereas NoSQL are non-relational dbs.
- Example comparing SQL and NoSQL for the same data and use case:
SQL NoSQL

In SQL, we can make separate tables for each of the Customers, In NoSQL, there are no tables or relations,
Products, and Orders. And then we can establish relationships hence each order is represented as a
between them, and when we need data that spans over multiple document, and we use embedded objects
tables, we just use joins. for the keys customer and products.
This would lead to data repetition.

The above method leads to data repetition, so


another way is to organize your data in
different documents. So here you have 3
objects, one for each of the details of
customer, product, orders. And then you will
have to link them together using references.
But this is clumsier and this can be done much
faster using NoSQL.
When you have a lot of relationships amongst data, SQL is a If your use case is having a lot of one-to-many
better choice for a database to go with. relationships (for example, instagram's single
user has data like name, id and multiple posts.
So each user has an array of posts.) So when
you have a single user generating a lot of
content, here it's one user to many posts, then
it's much easier to use mongoDB

Choosing between SQL and NoSQL (practical scenarios)

Hence, depending on the structure of your data, you will have to choose your database.
- When you have a lot of relationships amongst data, SQL is a better choice for a database to
go with.
- However, if your use case is having a lot of one-to-many relationships (for example,
instagram's single user has data like name, id and multiple posts. So each user has an array of
posts.) So when you have a single user generating a lot of content, here it's one user to many
posts, then it's much easier to use mongoDB

- One of the reasons to use NoSQL over SQL is scalability (SQL gets slower and slower as your
data sets size increases).
- Because of the way mongoDB organizes its data into smaller chunks/documents of, where
each record or row is represented as a JSON object. So this allows for a distributed system and
so your database can be distributed over multiple computers.

- Hence SQL is better querying for complex relationships (that span over multiple tables).
- MySQL databases scale vertically hence requiring more infrastructure and expense (hence
difficult to scale). Whereas, NoSQL scales horizontally and hence this allows for a
distributed system and your database can be distributed over multiple computers, hence
easier scalability.

Summary of Comparing the two most famous SQL and NoSQL databases.

- With every database there are 4 main operations (CRUD) you will perform:
● Create
● Read
● Update
● Destroy

Difference between Download and Install (and some Ubuntu essentials)


- Download is when you get/'download' the folder/zip/package from the internet onto your local
machine. But to be able to run and use the package, you need to install it after downloading.
This spreads over the package across in the directories from where it will look for later on. So
the usual paths where it stores in are /user/bin, /user/bin/bash
- The '/' is the root directory
- The '~' is the home directory
- In ubuntu, to install any new software/package, we use the 'apt get', which does both
downloading and then installing. Hence this is called the package manager.
- So the package manager in python is pip, for javascript its node, similarly for ubuntu the
package manager is apt.
- When we run the 'sudo -s' command to enter the root user, we make the shell enter as the
root user. The root has all privileges of wrx (write, read, execute), unlike all the other three
modes of users which is [Owner, Group, Other], whose privileges you can see by executing the
ls -l command.
- The 'wget' command only downloads, and it does not install (i.e. it doesn't spread over the
installed packages into the usable directories yet), since it's not a package manager like apt is.

- Whenever you learn about a new database, always first wrap your head around how you will
perform CRUD operations in this db.
- run the command: mongo , to get mongo client started
- When it opens, you see an angular bracket, and then you can enter the command 'help', and it
will give you all the list of commands you can execute there.
- To create a database, the command is: use shopDB
- To check the current database which its using, command is: db
- Collections in mongodb are similar to tables in the SQL world. They are a collection of
documents. And a document is simply just a single data record (like in SQL).

- Collections (like tables)


- Documents (like rows)

Note: Whenever you use mongo locally, you need to get the mongod server up and running,
which is the mongod server. And then to use the mongo client, we run the command 'mongo'.

Command to run mongod (mongo's server) from terminal is:


sudo systemctl start mongod
And then to stop the mongod server:
sudo systemctl stop mongod

Important Unix commands (and their explanations)


- netstat -antp | grep mongo
netstat is a program which tells us the 'network statistic', and we provide the flags -antp (-a, -n,
-t, -p) where -t means the TCP protocol, hence this will show all those network connections
established over a TCP protocol. Just the command 'netstat -antp' would give the output to the
standard output (standard output is the terminal), and here we have piped that output using the
pipe operator '|', which sends this output to the next command after the pipe. Which is the grep
command which basically does regex matching. So it matches the word 'mongo' with all the
lines returned by the previous command and eventually prints it on the screen.
- This netstat command tells us the ports and the processes listening at those ports.
- Whenever a process starts it gets certain fd's (file descriptors) such as 0 for standard output, 1
for standard input, 2 for standard error, etc.

- To Create in mongo, we use


● db.name_of_collection.insertOne() ← inside the bracket we get to insert a
javascript object
ex: db.products.insertOne({ id : 1, name : "Pen", price : 1.20 })
● db.name_of_collection.insertMany()
- To view all the collections, do: show collections
- So common commands:
show dbs, use XYZ_db, show collections, db

- To Query (Read) in mongo db


db.name_of_collection.find()
Find takes 2 optional parameters, which are query and projection. (Read documentation,
mongodb has very very good documentation)
- db.name_of_collection.find( query, projection )
example:
db.products.find( {id : {$gt : 1}}, { name : 1, _id : 0 })
Here query is like the where clause of sql where you specify conditions, and the projection
specifies what all columns you want to select, so you give it 1/true or 0/false specifying what all
columns you want to select.

To Update
- Similar to the query/res, the syntax for this is:
db.name_of_collection.updateOne(query, update_action)
- For example:
db.products.updateOne({id : 1}, {$set : {stock : 32}})

To Delete
- db.collection_name.deleteOne(query, projection)

- So each document in mongo is a javascript object, and a collection of these objects together
make a collection.

-- And note that in most of these mongo functions, there are 2 optional parameters. Of which the
first parameter is the query part where you specify the 'where' condition, and since this is a
javascript object, we use embedded objects to write this 'where' condition.
The second parameter specifies to which columns/fields you want this operation to be applied
on. (In SQL this is the part where we would have done select col1, col2, col3).

Establishing relationships in mongo


- Every document is represented by a set of curly braces. If we want to have a document to
represent the reviews of that product, then we can embed that inside the main products
document (embedding is basically an object inside another object).
- So this kind of one to many relationship, like in our example, where one product can have
many reviews.
Here the reviews field is an array of embedded objects, each of which is an object representing
information about the review.
So this is a one-to-many relationship which is well suited for mongodb databases to store.
Till now we did MongoDB in its purest form, by directly writing commands in the shell.

- When you are creating a Node app that needs to connect to a Mongodb database, there are
essentially 2 options for you to choose from:
● Native MongoDB Driver
● Using an ODM (Object Document Mapper) like mongoose.
The most popular way of working with mongodb when using node is by using this
package called mongoose.

Native MongoDB driver


- The driver is what will enable our mongodb to interact with our application.
- We are trying to glue together mongodb with our nodejs module.
- So make a new folder, and initialize new module there (npm init), and do
npm install mongodb
- Whenever you see 'asserts' in nodejs, they are basically here to do with testing and
validations. In this use case, it validates our data entry and the connection to the database.
- When working with mongodb, the port used (by convention) is always 27017
- Hence, using this native mongo driver is very wordy and long, and hence most developers use
a module called mongoose.

- Remember that anything inside a pair of curly brackets is a document.

Mongoose

- Mongoose is also a node package.


- Mongoose is what is called an ODM (Object Document Mapper), and it will allow your nodejs
app (which speaks the language of javascript objects) to be able to talk to your mongodb
database (which speaks in the language of documents and collections and databases).
mongoose.connect("mongodb://localhost:27017");

here we are telling mongoose to establish a connection and connect to the server listening at
port 27017. (before doing this we must start the mongod server from the terminal by running in
the terminal the command: sudo systemctl start mongod). So the line
"mongodb://localhost:27017" means that the type of protocol we are establishing is 'mongodb
protocol' (just like if we had http protocol we would have written 'http://...') and then the IP
address which here is using local host, and then the port number which here is 27017.

Understanding Networking Protocols


- The most basic protocol is IP.
- IP(Internet Protocol) establishes a connection between two machines on the internet by
identifying their IP addresses.
- On top of IP (as the next hierarchical layer on it), there are options of two different types of
protocols which are: TCP and UDP.
- Properties of TCP: It establishes a very 'reliable connection' by the use of sequence number
and makes sure the data packets are received at the other end of communication. Hence TCP
is famous for its reliability and making sure that the exact data is received at the other end.
Hence TCP is the most popular protocol used. And all these other protocols such as http (and
here in our case the mongodb protocol) sit hierarchically on top of this TCP protocol).
- Properties of UDP: It does not establish a connection like TCP does, instead it just directly
sends the data packets, hence this is known for its faster speed. But since it does not establish
a connection, it's not as reliable. Cases where little damage of data is acceptable is where UDP
can be used, such as a phone call where the data is voice audio and slight damage won't matter
much, and it would want faster communication, hence UDP is the best here.
- So if TCP notices that a packet got damaged on the way, it would resend the packet (hence
reliable and ensure receival of data), unlike UDP which does not bother after sending the packet
once.

- So in this case, the client is the mongodb driver itself (which you got by installing from npm, the
mongodb module), and then mongoose is just a tool/package that makes it shorter and easier to
write code which you would have to otherwise have written for mongodb's package directly.
(This is just like how jQuery makes writing javascript code shorter, similarly mongoose makes
writing mongodb code easier).

- In mongoose, we first create a schema (note: this is flexible and not supposed to be followed
strictly like we need to in SQL)
const fruitSchema = new mongoose.Schema({
name: String,
rating: Number,
review: String
});

- Now, we use the schema to create a mongoose model.


- In mongoose, ‘Models’ are higher-order constructors that take a schema and create an
instance of a document equivalent to records in a relational database.

const Fruit = mongoose.model("Fruit", fruitSchema);

- mongoose.model( <singular_collection_name> , <schema_name> );


- Here, we create a collection of fruits by giving the name that each of them is a Fruit (mongo
will use lodash behind the scenes and pluralize this to give 'fruits'), and the second argument is
the schema.
- Now, we need to create a document from the model that we specified on top, and so we must
try and follow the schema that we laid out.
const fruit = new Fruit({
name: "Apple",
rating: 8,
review: "Pretty solid."
});

fruit.save();
- then doing .save() method on the document saves this fruit document into a fruits (Fruit)
collection inside our fruitsDB. These 3 steps are basically what comprises our Insert command.

So the steps of using mongoose are:


● First connect to the mongod server
● Make a schema (using mongoose.Schema)
● Make a model of that schema (basically an instance of the document, using
mongoose.model)
● Make documents (data entries/records for your collection)
● And then save these documents to your database (using document_name.save())

- Now, to do a find and search for the fruits inside the Fruit collection,
Fruit.find(function(err, fruits){
if(err){
console.log(err);
} else{
console.log(fruits);
});
- This callback function takes error as the first argument, and the fruits collection as the second.

- Data validation in mongoose is much simpler compared to doing it in using a pure mongodb
data driver (in which we had to multiple assert statements).
- Mongoose has these builtin data validators which you can provide while creating the shema,
so you can specify for an attribute, say for the rating of the fruits:
rating: {
type: Number,
min: 0,
max: 10,
required: [ True, 'You must specify the rating!!']
}

- To update and delete data using Mongoose,


Fruit.updateOne({_id: "6088a2abdee7302a29d2cdb2"}, {rating : "9"},
function(err){
if(err){
console.log(err);
}else{
console.log("Successfully updated the document");
}
});
- From the documentation, updating uses the method .updateOne(), and takes 3 required
parameters and 1 optional parameter (see documentation).
Here the 3rd parameter is the callback function.

- To delete, we do .deleteOne()
- Read the mongoose documentation for all the methods in detail (under the 'Queries').
- Note that while working with any new db, the first important thing is to understand how to
perform CRUD operations in this db.

Establishing Relationships and Embedding Documents in Mongoose


- We do this by embedding objects inside other objects to establish relationships (usually one to
many relationships).

mongoose.connect("mongodb://localhost:27017/todolistDB", {useNewUrlParser
: true, useUnifiedTopology : true});

The first argument has the following components (and their meanings):
● mongodb:// Here mongodb is the protocol establishing the communication
between the client and the server (like we saw http previously).
● localhost This is the IP address of the machine
● 27017 This is the port on which the mongodb server is connected to and
is listening at
● todolistDC This here refers to the database. If it already exists, that will be
used. Otherwise it will create a new one.

- To insert a single document into the db using mongoose: doc_name.save()


- To insert many, we use the insertMany() method. Note that there is no method called
insertOne().

Synchronous vs Asynchronous

- Javascript at its base is a synchronous, blocking, single-threaded language. This means that it
reads through the code line by line from top to down executing one operation at a time (just like
all languages do).
- But, javascript is special and since it's used in multiple operations such as loading contents to
a website, or reading from a database, etc. it cannot wait till one that operation of getting data
from database executes, since that might take time. And javascript needs to be fast, especially
websites need to be quick, hence in such cases javascript behaves asynchronous.
- So, if a statement in the code is doing a find from a db, js will create a new thread for this, and
continue with the statements that follow (the ones that are after this).
- This asynchronous nature of javascript is also to support callback functions in js which are very
widely used.
- Hence if you want a piece of code to be executed only after another piece, you will have to
write it inside that same callback and nest these inside one another (because if you don't, then
you will write is after this statement, which due to the asynchronous nature here will not be
executed in the desired order).

Code:

Output:

Important example
- The first statement encountered is for a db fetch, which it goes to do. And since js is
asynchronous, it will not wait for the db results to come back. Instead it will continue with the
next statements that follow.
- The setTimeOut function will execute its callback only after 3000 ms, but it will continue to do
the next statements after it.
- The next statement is the console for 'This is after timeout function'. Hence this is printed out
first. And then the db statement finishes its fetch, after which it console logs 'Inside function'.
And then, after 3000 ms are over for that Timeout function, it will console log its contents which
is the 'Outside function'.
- Hence, notice in this code, we wanted to do the render function only after it got back contents
from the db, we had to nest it inside that db fetch function itself (because if we wrote it outside
after it, then it would get executed earlier as seen due to its asynchronous nature here).
- This is one way of making sure your code is consistent and behaving as expected. But this
nesting might lead to unreadable code. Hence there's another way to specify that you shall
execute a block of code only after another is by the use of 'promises'.
- Watch this for reference (for asynchronous js):
https://www.youtube.com/watch?v=PoRJizFvM7s
- Express uses route parameters and allows us to create dynamic routes.
- When you want to use the value from the forms that were posted/submitted, we use body
parser for that, and tap the values using: req.body.name_of_input_in_form
- If we need to pass more stuff, we can also assign values to other html items like buttons, etc
and then again tap their values using the name that we assigned to the button.
- In cases when there are no other html elements, we can use an input html element with a
special type="hidden", which is just solely used for this purpose, i.e. to pass values from the
html to the js and being able to tap those values from js.

- Note, when dealing with route parameters, we use req.params.x


But when dealing with data returned from a form that was submitted to a post request, we use
req.body.x

{$pull: {items: {_id: checkedItemId}}}


- This means that we pull from the items array an item that has an id of 'checkedItemId'.

Deploying Webapps with Databases

- Like we used Heroku to deploy our Nodejs server, we need another such server (on the world
wide web) which can hold our database.
- Mongodb provides its cloud services called MongoDB Atlas.
MongoDB Atlas will host our database and serve up the data whenever it's needed. So, our
nodejs will be able to make necessary requests to our MongoDB Atlas (both of which are hosted
on external servers on the internet)

- Hence, we are going from


http://localhost:3000
mongodb://localhost:27017
to
http://yourapp.heroku.com
mongodb://cluster0.mongodb.net:27017

on the servers hosted globally


- After creating an account on mongodb atlas,
go to database access and add a new user with 'atlastAdim' privileges.
These are the mongodb users which will be able to communicate with the database on
mongodb atlas.
- Then do connect from the mongo shell, and it gives you a command to run which you execute
in your shell. This now gives us an active session with the mongodb shell that's running on the
atlas cluster.

Building your own RESTful APIs from scratch


- REST: Representational State Transfer
- Client talks to the server via the HTTP Request. The server can respond only to certain APIs
which it exposes.
- REST is an architectural style for designing APIs. It's like a set of guidelines that need to be
followed. There are other such styles, such as SOAT, GraphQL, etc.

What makes an API a RESTful API?


- Rules that APIs must follow to be RESTful, two most important ones are:
● Use HTTP Request Verbs
● Use specific pattern of routes/endpoint URLs

- The 5 http verbs are:


1. get, (like Read)
2. post, (like Create)
3. put, (like Update)
4. patch, (like Update)
5. delete (like Delete)
These are pretty similar to CRUD in databases

- RESTful Routing

- Robo3T is a graphical user interface used with MongoDB.


Install on ubuntu with command:
sudo snap install robo3t-snap
It's basically a mongo client, so you need to make sure your mongo server is listening on port
27017.

Use Postman to send requests to the server.


- To make POST requests through postman, use the x-www-form-urlencoded format since this is
the format that body parser can interpret.
Authentication

- Handling login and password for users. Authentication: keeping secrets.


- There are different levels of security- 6 levels.

- Difference between authorization and authentication-


Authentication is the process of verifying who a user is, while authorization is the process of
verifying what they have access to.

Level 1 Security
- The lowest level of security. Creating accounts for users, storing their email and password.

Level 2: Encryption
- Involves the use of encryption keys. Encoding and decoding, the other person cannot
understand the message unless you know how to decode that.
- With node, we can use a package called mongoose-encryption.
- It encrypts when you call .save() and it decrypts when you call .find().

- We store sensitive information in environment variables, such as API keys and such sensitive
information.
- We make use of node's module named dotenv.
- Using Environment variables to keep secrets safe.
- We use a file called .env, which is a hidden file and we will add our environment variables to
this file. Then to make use of these variables in node, access them via process.env.API_KEY
- And then add .env to your .gitignore file.

Level 3: Hashing
- Hashing takes away the requirement for having an 'encryption key'.
So how do you decrypt the secret without the key? Answer is that you don't.

- It's almost impossible to turn the hash back into its original password.
- So when a user registers, the hash of the password is generated, and this hash is stored.
Once the user logs in again, another hash is generated for the password they entered and these
2 hashes are compared. If they match, then it's correct.
Hence the password is never stored; only a hash is stored.
- In node, we use the package md5 for this.

Difference between Encryption and Hashing


The key difference between encryption and hashing lies in the fact that in case of encryption,
the unreadable data can be decrypted to display the original plaintext data with the help of the
right key, whereas in hashing, this cannot be done at all. Encryption of data is done through the
use of cryptographic keys.
- Issues with this hashing approach: it's easy to hack small passwords (upto 6 to 8 letters) since
hackers can construct a hash table from dictionary words and brute force all the 6 letter words
possible.

Level 4: Salting and Hashing


- Adding an additional 'salt', random number, to increase the complexity of that hash.

- The 'salt' is like another random text/number/salt.


- On the databases, we would be storing the salt and the hash.
- To make it even more secure, you can do multiple salt rounds. The more rounds you do, the
saltier your password.

Level 5: Cookies and Sessions


- The active cookie maintains the authentication for that browsing session.
- Passport is authentication middleware for nodejs, for adding cookies and sessions. The
package we use is called express-session.
- Libraries used of nodejs: passport, passport-local, passport-local-mongoose

Level 6: OAuth
- OAuth is an open standard for token based authorization.
- Third party login, by allowing users to login via google or facebook, and allowing these third
party websites to authenticate the users.
- Why is OAuth special?
1. Granular level of access.
The app developer can determine what kind of data they need from the user's facebook
account, and request those accordingly.
2. Read / Read + Write Access.
You can ask for read or both read and write access.
3. Revoke access.
The user can revoke access via these 3rd parties, like google or facebook.

- One user logs into the third party website (google or facebook), the third party sends them
either an 'authentication code', and an 'access token'. Via the access token, our app can
further ask for more pieces of information from the third party website.
-
REACT Js

- In react, it is as if we are creating our own html elements like so

- We use codesandbox for all the tutorials


- The convention is to always create a div html element which has an id of 'root'. And this is the
root of our react application, and everything that we create will be inside these divs.
- So we will not be touching the htm file anymore, instead we only write reactjs code in the
javascript file.
- ReactDOM.render() takes 3 arguments,
● What to show
● Where to show
● Optional callback to tell us when that render function has competed

- So, this line of code allows us to inject html code into our website like this:
ReactDOM.render(<h1> Hello checking? </h1>, document.getElementById("root"))

- React works by creating these jsx files, where we have html right in the body of a javascript
file. What happens behind the scenes here is that a compiler converts the html code to
javascript code. This is done by the module 'react'.
So inside the react module, there is something called Babel which is a javascript compiler.
- Babel is the javascript compiler used internally in React and it converts our javascript to very
simple javascript that is understood by all kinds of browsers.
Hence we can even use es6 and stuff with react, since it has all these modules internally
making sure it will work on every kind of browser.
- Hence we can use 'import' statements instead of require statements, which actually follow es6
format.
- ReactDOM can take only a single HTML element for the first argument. If we want to add
more, then it directly wont allow. Hence to get over it, we can wrap up all these html tags inside
a single <div> tag.
- Hence this is how we inject html code inside javascript code.
- The html tag we see in this syntax is neither a string nor HTML.
It is called JSX, and it is a syntax extension to JavaScript.

- Hence, JSX allows us to insert html inside of javascript files, and also allows us to insert
javascript inside that html itself.
- To add javascript code inside the html part of code in the js file, we write it within {} curly
braces. You can add any javascript expressions inside these curly braces. Although you cannot
add javascript statements like if and else loops.
Means that you can only add javascript that evaluates to a value inside the {} braces, and
cannot write statements like if else loops.
- Hence, with jsx, if you are writing js inside the html, you can write expressions but not
statements.
- Make sure that you write the attributes in camelCase in the jsx part.
- We make use of javascript properties in jsx, such as className in the html attributes instead
of class.
- Hence note that it is jsx, and not html even though it looks very similar to it.
- You can add the style attribute to jsx, and this style attribute takes a javascript object as its
argument. Although the recommended method for adding styles in react is by using the class
property of css itself.

- Components in react:
Since files can get really long, we split them up into components where each component has a
small part of the html file (rather jsx file).
- You can write a function which returns this html code, and then use that function's name as if it
were an html tag itself. Hence this way you can create custom html tags, each of which are
components.
- And by convention, name these functions with PascalCase.
- Make sure you write the self closing tags.

- And we can now move each of these functions for every component into separate jsx files and
then import them (since we have es6 with reactjs). Make sure you import React in all of these
jsx files.
- Hence the best practice is to move all the html (rather jsx) code out of this javascript file.
- This is the format we use to structure all Reactjs files, where we have the whole component
tree defined in the App.jsx file, which has all the custom components imported from other jsx
files which have each of those individual components.
- Import and export modules
There can be only one single default export per file. For importing the non-default ones, we use
the curly braces {}.

- For using react on vscode for our local development, we use npx which is a package runner
tool which comes with npm.
- 'npx create-react-app my-app' : Run this command on the terminal to create a new react
project.
This will install 'react' and 'react-dom' as we've seen previously, and will also install
'react-scripts' which allows us to run our react app locally and serve it up on our browser.

- Like we can have attributes associated with each html element, for example
<input id="firstName" class="userName" placeholder="Enter your name" value="Shi" />
Then you can obtain the element in the developer console tab and then access each of these
attributes of the html elements.
Similarly for the custom defined html tags, like <App/> or <Header/>, we can give it our custom
attributes, and these are called Props or properties.
It's almost like we are calling a function, and passing these values as props.
- So, inside our custom components (of html elements like <App/> and <Header/>), it sees each
of these as custom properties. So you cannot do the usual stuff like className, etc. These can
only be done on html's original tags and original elements like 'h1' or 'div', etc.
- The React Dev tools section shows us the React DOM Tree (like the chrome developer tools
showed us the HTML DOM tree).
In the React Dev Tools you can see each of the react components and their props as well.
- The chrome extension allows you to view the react component tree. You can view it like this in
the developer tools-

Mapping Data to Components


- The map function is a javascript function and is really useful for handling arrays.
- We apply the .map() method on the array, and pass it a function as the argument. That
function takes each of the elements of the array as its argument.

Map, Filter, Reduce


- All these are methods that we can call on an array, and they take a function as its argument,
i.e. callback function. They allow us to go through each element in the array and perform that
function for every element in that array.
You can do each of their functionalities using the forEach() function as well.

- Since we cannot use if else 'statements', we convert that logic into expressions where we do
conditional rendering. To do this, we make use of ternary operators and the && operator.

States in Reactjs
- We need the concept of states in reactjs in order to make the apps more interactive.
- The UI of your app is a function of the state of your app.
- So we make use of conditional rendering, and have the user interface being dependent on the
value of a state variable.
This kind of programming is called Declarative Programming. The other kind of programming is
called Imperative programming.

- Hooks allow us to hook into the state of our app and read or modify it.
One of the popular ones is called useState.
- One of the rules for using hooks is that you must use them inside a functional component.
- We use states for our website to update dynamically reflecting the updated state, without
having to refresh the webpage again.

- The useState hook is like:


const [state, setState] = React.useState(initialState);
The second argument returned is a function which we use to update the state, and the first
argument is the value of the state itself.

- Diff b/w state and prop


State is inside of the component, whereas prop is handled outside the component. You pass the
prop to the component.
- Note that you can use hooks only inside of function components, and not inside class
components.
- You cannot write hooks inside of if statements or loops, etc. You cannot nest them.
- When you update a state, you re-render the component.
- State is a variable/object in react, and it reacts to change in your react app and automatically
updates the component.
Normal variables don't react to changes.
Whereas if we use states, Reactjs will know what part of the UI to re-render.
- Props are only read-only, and cannot be changed. Whereas, states can be changed.
- So whenever you want to be able to change/modify/update data, we use states.
Diff between Functional component and Class component
- We use functional components when we are writing only a presentational component, which
does not have its own state or needs to access a life hook.
- Use class states when you need state or need to access lifecycle hooks.

- Example of 'state' and class components,

- Handling events in React is very similar to handling events on DOM elements. The only
difference is that when writing events in React, they must be in camelCase.
- Best video series on React, very practical and easy to understand.

- You can update the state using this.setState(). An example of using this is when let's say you
do a handleClick event and on click you change the state, and set it to something else.

- One of the ways to have conditionals in react is this-

Note that you cannot use if and else 'statements' in place of this, since it's a rule in react that
you cannot have statements like this, instead only have expressions.
Hence this method is used to render something (some react component) only when the left
hand side condition is true.
- Another way of doing this is to use the ternary operator.
- useState()

TO BE CONTINUED!!

You might also like