Banuprakash C
Full Stack Architect, Corporate Trainer, CO-FOUNDER: Lucida Technologies Pvt Ltd.,
Email: [email protected]; [email protected]
https://www.linkedin.com/in/banu-prakash-50416019/
Softwares Required:
- Chrome Web browser with following extensions: 1.1) add React Developer tools 1.2) add Redux DevTools 1.3) Lighthouse
- Visual Studio Code
- NodeJS Latest LTS
JavaScript: JS needs JS engine ==> V8, SpiderMonkey, Chakra, Continnum, NashHorn
var g = 10;
function doTask() { var a = 5; return g * a; }
function doTask() { var x = 10; console.log(x); }
Engine introduces semicolon function add(x,y) { var res = x + y; return res; }
var obj = { x : 10, doTask: function() { return this.x; } }
obj.doTask(); // 10
var fn = obj.doTask; // this context will be global; not obj's
var fn = obj.doTask.bind(obj); // this refers to "obj"
OOP: credit() and debit() ==> state of object Account's balance ==> tightly coupled
Functional Style of Programming ==> High Order Functions 1) functions which accept function as argument 2) function which returns a function functions as first class members
HOF:
function forEach(data, action) {
for(var i = 0; i < data.length; i++) {
action(data[i]);
}
}
var elems = [56,3,72,2];
var names = [ "a", "g", "j"];
forEach(elems, console.log);
forEach(elems, alert);
-----------------------------------
Commonly used HOF:
1) filter
2) map
3) reduce
4) forEach
--------------------------------------------------------
map function to return names of product
var results = map(products, mapperFn);
console.log(results); // [iPhone, OnePlus, HDMI ]
Tea break: 15 min
--------------------------------------
HOF: function which returns a function
function greeting(msg) {
return function(name) {
return msg + " " + name;
}
}
var g1 = greeting("Good Morning");
function greeting(msg, name) {
return msg + " " + name;
}
greeting("Good Morning", "Rakul");
greeting("Good Morning", "Rahul");
var g2 = greeting("Good day");
g2 closure ==> Good Day
Memoize:
getEmployee(23); ==> REST call and cache it
getEmployee(23); ==> cache hit
Browsers ==> ES5
Transcompile; Transpile ES6 ==> ES5 Babel; Tracuer
Babel is a free and open-source JavaScript transcompiler that is mainly used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript that can be run by older JavaScript engines
ES2015 features:
- Scope variable: let and const are used for block scope
Prior to ES 6: No block scope; only global and function scope
var g = 10;
function doTask() { var a = 100; if(a > g) { var b = 20; c = 40; } console.log(g,a,b,c); }
doTask(); console.log(g,a,b,c);
ES 6:
var g = 10;
function doTask() { var a = 100; if(a > g) { const PI = 3.14159;// block scope let b = 20; // block scope c = 40; } console.log(g,a,b,c); // b is not accessible }
- arrow operator:
let add = (x = 0, y = 0) => x + y;
add(); add(5); add(5,6);
- Destructing and split operator
3.1 )Array var colors = ["red","green","blue","orange"];
eS5 aproach: var red = colors[0]; var green = colors[1];
ES6:
var [r, g, ...others] = colors;
3.2) object var p = { "id": 1, "name": "iPhone", "price": 124447.44, "category": "mobile" };
var {name, price} = p;
console.log(name) ; // iPhone console.log(price) ; // 124447.44
or
var {name: n, price: } = p;
3.3)
var elems = [4,5,7];
var data = elems; // reference
data[0] = 100;
var values = [...elems]; // copy of elems to values
change values won't effect elems
var elems = [ {"name": "a"}, {"name" : "b"}]
- New String literal [ tick]
var name = "Smith";
var place = 'Blore';
var msg = This is my First Line <br /> Name : ${name}
;
var comp = "
var comp = ` <div>
`; ---------------- Promise API
Async function ==> side effects ==> REST call, timeout, api call
Sync fn: function doTask() {}
let res = doTask();
console.log("end"); // blocked
Async fn: defered [ Future/ Completable Future] => resolved or rejected function doTask() {}
doTask().then(
(resolved) => ...;
(rejected) ==> ..;
).catch(ex) {
console.log(ex);
}
console.log("end"); // not blocked
fetch() returns Promise fetch('http://jsonplaceholder.typicode.com/users/1') .then(respose => respose.json()) .then(body => console.log(body)) .catch(ex) {}
- async and await to resolve callback issues with Promise API
-
Generators ==> to return multiple values over stages
function* dataGenerator() { console.log("task 1"); console.log("task 2"); yield "first output"; console.log("task 3"); console.log("task 4"); yield "second output"; }
let iter = dataGenerator();
let d1 = iter.next(); if(!d1.done) d1 = iter.next();
Day 1 Recap: Functional style of programming ==> HOF; closure ES2015/ES6 features ==> Babel / Traucer ==> Precompiler/ Transcompiler / Transpiler let, const, arrow, default parameters, destructing, spread operator, PromiseAPI, async and await, generators Day 2
Node.JS
$ node --version
==> JS Environment with default V8 JS engine configured
==> Developed using C++ [ C++ libraries + JS API] + [ fs, http, crypto, url, ..]
==> libuv is a c++ library [ thread pools ]
1) Use it as a build enviroment for client side JS web application
==> many librariies + many js files + also we may use [ ES2015 + typescript + CoffeeScript + Livescript + DART]
Transcompiler [ BABEL / TSC]
2) Run JS Build Tools [ Grunt / Gulp / Webpack] for Automation
Grunt is a JavaScript task runner, a tool used to automatically perform frequent tasks such as minification, uglify, compilation, unit testing, and linting
myFile.js ==> myFile.min.js
3) Build APIs ==> RESTAPIs / GraphQL ==> What Spring Boot / ASP.NET
==> Real time streaming of data [ Spring Boot with Netty instead of Tomcat]
4) Build standalone application
=============
NodeJS Modules ==> NPM ==> Node Package Manager ==> install dependecies for your project
NPM ==> same Maven / Gradle / PIP
----------------------------
package.json ==> pom.xml
==> dependencies [ jQuery, react, react-dom]
==> devDependices [ babel, tsc, ESLint]
==> scripts [ compile, lint, start, test]
npm init -y
Webpack ==> JS build tool ==> bundler
index.html
<script src="jquery.js"></script>
<script src="a.js"></script>
<script src="b.js"></script>
<script src="c.js"></script>
<script src="d.js"></script>
vendor.js
bundle.js
<script src="vendor.js"></script>
<script src="bundle.js"></script>
"webpack": "5.33.2", ==> Exact version
"webpack": "^5.33.2", ==> Minimum version required
"webpack": "~5.33.2", ==> need Major version of "5"
without package.json:
npm i webpack webpack-cli babel-loader
with package.json:
npm install
Module System: 1) CommonJS module System compute.js module.exports.add = function() {
}
other file
var comp = require('compute')
comp.add();
2) ES6 module system
compute.js
export function add() {
}
other file:
import {add} from './compute';
function Person(name){ this.name = name; }
Person.prototype.getName = function() { return this.name; }
npm run build-dev
bundle.js 6.04 KiB
IIFE: ( var a = 10; function one() {
} function two() {
} )();
( var a = 50; function one() {
} function three() {
TypeScript
JS: var x = "Raj";
x = 10;
first.ts ==> tsc [ check the types] ==> first.js [ JS engine]
Typescript types:
-
Number let age:number = 30;
age = "A"; // tsc throws error
-
String
let name:string = "Tim";
name = 10; // tsc error
-
Boolean let flag:boolean = true;
-
arrays let elems:number[] = [6,3,7,2]; or
let elems:Array = [5,2,5,7];
-
enum
enum Colors { RED, GREEN, BLUE };
let clr:Colors = Colors.GREEN;
-
any let data:any;
data = doTask();
data["name"] ; // can use it
-
unknown let data:unknown;
data = doTask();
data["name"] ; // error
-
undefined, void, null
function add(x:number, y:number) : number { return x + y; }
let res:number = add(5,7); // valid
add("a", 6); //error
function doTask(): void { console.log("Hello"); }
interfaces :
-
to declare a Shape
interface Person { id:number, name:string, address?:string }
function addPerson(p:Person) : void {
}
addPerson({"id": 2, "name": "Raj"});
addPerson({"id": 2, "name": "Raj", "address": "some streeet"});
addPerson({"id": 2}); // error
interface for contract:
interface Timer { setTimer(time:number): void; }
class Game implements Timer { //
setTimer(time:number): void { // body }
} ========================
class
class Person { constructor(name:string, age:number) { this.name = name; this.age = age; }
getName(): string {
return this.name
}
}
class Person { constructor(private name:string, private age:number) { }
getName(): string {
return this.name
}
Decorators: Angular
@Component({
selector: 'app-product',
style-url:
template-url:
})
class Product {
name, price
}
=======
Mobx
@obverser
class SomeClass{
}
=========== Product.ts class Product { constructor(private name:string, private price:number) { }
getName(): string {
return this.name;
}
}
let p = new Product("iPhone", 89000.00);
console.log(p.getName());
@Component({
selector: 'app-bank-account',
template: Bank Name: {{ bankName }} Account Id: {{ id }}
})
export class BankAccountComponent {
}
@Component({ selector: 'app-product',
}) class Product{
Server side Rendering and Client side rendering
Rendering ==> data to presentation
Server side Rendering:
- Servlet and JSP
- ASP, ASP.NET
- PHP
- Flask
- JS: Pug, JADE, EJS
Client Side Rendering: server sends data; redniering is done on client machine [ payload ==> xml, json, csv]
-
Templates Mustache, Handlebars, Underscore, jQuery templates
-
View Library ( V part of MVC ) React.JS
-
Framework ( Model View Controller) Angular, Backbone, Ember ========================================
SPA ==> Single Page Applications
-
handle multiple modules
-
Data ==> Presentation
-
Different routes for different URIs index.html http://adobe.com/products/mobile http://adobe.com/products/tv http://adobe.com/products/mobile/iphone http://adobe.com/products/mobile/pixel2
http://adobe.com/products/customer/banu/orders
Why routers?
- SEO
- Bookmark
- History API
-
Dependency Management =======================================================
-
CodePen: JavaScript PreProcessor: Babel included : react and react-dom libraries
============= HTML:
JS: let Welcome = React.createElement('h1',{style:{'color':'red'}}, "Welcome to React!!!");
ReactDOM.render(Welcome, document.getElementById("app"))
===========
functional components: simple js functions which returns JSX ==> JavaScript and XML
Babel ==> converts Functional Component into React.createElement // JSX function Welcome() { return
}props ==> mechanism using which parent component passes data to child component
// JSX function Welcome(props) { return
}ReactDOM.render(, document.getElementById("app"))
==========================
// JSX
function Welcome({title, info}) { return
}==> only executable modules npm i -g babel
==> project specific dependencies "node_modules" of the project
Recap: Functional Components, ES2015, NodeJS; package.json; NPM webpack with ES2015; TypeScript
codepen.io React.createElement() React Functional components
DOM and Virtual DOM
DOM: document.getElementById() document.getElementByTagName() document.append(...) document.createElement()
React renders the parent and child components whenever props or state changes
class component
class ProductComponent extends React.Component { state = { "products": [], "count": 0 }
handleClick() {
}
handleChange() {
}
render() {
return JSX
}
Account == > balance is state; credit and debit are behaviour
npx create-react-app customerapp
Scaffolding code with webpack; http-lite-server; adding all npm requirements
=============================================================== "react": "^17.0.2", React.Component, React.createElement
"react-dom": "^17.0.2", ReactDOM.render()
"react-scripts": "4.0.3", ==> provides scripts to run webpack
"web-vitals": "^1.0.1" ==> Run stats like FCP, TTFB, LCP
Unit and Integration Testing: "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10",
"dependencies": { "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", "react": "^17.0.2", "react-dom": "^17.0.2", "react-scripts": "4.0.3", "web-vitals": "^1.0.1" }
scripts: "start": "react-scripts start", ==> starts transpiler[Babel], starts http-lite-server, deploys on this server http://localhost:3000
"build": "react-scripts build" ==> bundle.js ; vendor.js
"test": "react-scripts test", ==> Unit testing
React props and state are keywords
any changes to props and state ==> react re-renders
Filter.js
Delete
OR
Testing React application:
JS Unit Testing Framework: Jasmine, Mocha, JEST
RTL ==> React Testing Library ==> built on JEST
Enzyme with JEST; Enzyme can be used to create Component for Testing environment mount(), shallow(), reder()
JS Testing ==> AAA ==> assemble, Action and Assert @Test
// test suite describe("testing customer list component", () => { it("test delete", () => { action assert });
test("test filter", () => {
action
assert
});
});
getByXXXX() ==> returns elemeent or throws Exception
queryByText() queryByPlacerHolderText('search by name') queryByAltText("logo"); queryByRole("button") queryByRole("input") queryByTestId("someid");
Multiple values: getAllByXX queryAllBy()
============
npm test npm test -- --coverage
===============================
{ "integrationFolder": "src/.", "testFiles": "**/*.spec.js", "viewportWidth": 500, "viewportHeight": 800, "baseUrl": "http://localhost:3000" }
customerapp> npm i -D cypress @cypress/instrument-cra
Recap: Functional component, Class Component, props and state, handle events [ using bind and arrow functions]
RTL ==> on top of JEST unit testing framework;
screen methods: debug() getBy; queryBy; findBy ==> any async components [ API calls => JSON => Component gets created ]
render() [ FCP ] ==> componentDidMount() ==> render()
npx create-react-app phoneapp $phoneapp> npm i bootstrap styled-components react-router-dom
"scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject", "cypress" : "cypress open" }
npm start npm run cypress
run all test specs in "cypress/integration/examples"
modify cypress.json to run our tests [ outside of src] { "integrationFolder": "src/.", "testFiles": "**/*.spec.js", "viewportWidth": 500, "viewportHeight": 800, "baseUrl": "http://localhost:3000" }
Phoneapp Application:
- React-router-dom
- styled-components
- React Context [ React 16+ ]
- fontawesome , google fonts
- bootstrap ==> RWD
React-router-dom
Router: differnet URIs should display different views http://adobe.com/ http://adobe.com/products http://adobe.com/locations http://adobe.com/products/acrobat http://adobe.com/products/dreamweaver http://adobe.com/employees
==> single page ==> index.html ==> Single Page Application
Why?
==> SEO
==> Bookmark
==> Navigation using History API [ HTML 5]
Styled components styled-components is the result of wondering how we could enhance CSS for styling React component systems
npx create-react-app phoneapp $phoneapp> npm i bootstrap styled-components react-router-dom
=============
class App extends React.Component {
render() {
<>
{this.props.children}
</>
}
}
React Context:
let PersonContext = React.createContext();
class PersonProvider extends React.Component { componentDidMount() { this.setState({ "name" : "Banu", "email": "someemail", "updateEmail" : this,updateEmail.bind(this) });
updateEmail(e) {
this.setState({
"email": e
});
}
render() {
return <>
<PersonContext.Provider value={{...this.state}}>
{this.props.children}
</PersonContext>
</>
}
}
class App extends React.Component { render() { return } }
function First() { return <> I am First </> }
class Second extends React.Component {
render() {
return <PersonContext.Consumer>
{
value => {
return <>
Name : {value.name}
Email : {value.email}
<button type="button" onClick={() => value.updateEmail("[email protected]")}>
Click
</>
}
}
</PersonContext.Consumer>
} }
Router:
http://localhost:3000/ ==> ProductList http://localhost:3000/products ==> ProductList http://localhost:3000/cart ==> CartComponent http://localhost:3000/abcsd ==> DefaultComponent http://localhost:3000/details/5 ==> DetailComponent
==========
share.zip
- place "img" folder in "public"
- Replace "App.css" in src folder
- place "data.js" in src folder
- place "Button.js" in "components" folder
- Replace "Navbar.js" in "components" folder
- place "context.js" in "components" folder
========================================================== Load the complete page
SPA with Router:
======================================================= Day 5 ----- Assignment: Using React.createContext to implement TODO application Context addTodo() ---------let ctx = React.createContext(); //
Provider ==> make state available to Consumer Views
<Provider value={{...this.state}}>
{this.props.children}
</Provider>
Cousmer views
<PersonConsumer>
{
value => {
return .... value.state ,....
}
}
</PersonConsumer>
Recap: Router ==> SPA; different URI, different views styled-components ==> styling DOM elements, applying css Context ==> avoid passing props to intermediary fontawesome ==> icons bootstrap ==> RWD
{ value => { return value.products.map(p => ); } } { function(value) { return value.products.map(p => ); } } { value => value.products.map(p => ); }function Person(){
doTask = () => {this.x}
function someTask() {
this ==> global context
}
Error: React components should have a single root element function App() { return
}
Solution: function App() { return
}
Problem: we introducted extra
function App() { return <React.Fragment>
</React.Fragment>}
</> }Chrome webextension:
- React Developer Tools
- redux devtools