Skip to content

Latest commit

 

History

History
1258 lines (906 loc) · 24.1 KB

README.md

File metadata and controls

1258 lines (906 loc) · 24.1 KB

React.js

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:

  1. Chrome Web browser with following extensions: 1.1) add React Developer tools 1.2) add Redux DevTools 1.3) Lighthouse
  2. Visual Studio Code
  3. NodeJS Latest LTS

JavaScript: JS needs JS engine ==> V8, SpiderMonkey, Chakra, Continnum, NashHorn

var g = 10;

function doTask() { var a = 5; return g * a; }

var result = doTask();

function doTask() { var x = 10; console.log(x); }

var res = doTask(); // value of res? ==> undefined

Engine introduces semicolon function add(x,y) { var res = x + y; return res; }

var total = add(4,5); // value of total ? ==> undefined

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 res = fn(); // res ? ==> undefined

var fn = obj.doTask.bind(obj); // this refers to "obj"

var res = fn(); // res ? ==> 10

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	

ES 2015 / ES 6

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:

  1. 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 }

doTask(); console.log(g,a,b,c);

  1. arrow operator:

let add = (x = 0, y = 0) => x + y;

add(); add(5); add(5,6);

let sub = function(x,y) { x = x || 0; y = y || 0; return x - y; }

  1. 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"}]

var values = [...elems];

  1. New String literal [ tick]

var name = "Smith";

var place = 'Blore';

var msg = This is my First Line <br /> Name : ${name};

var comp = "

" + name + "
"

var comp = ` <div>

${p.name} ${p.address}
`; ---------------
  1. 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) {}

  1. async and await to resolve callback issues with Promise API

  1. 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

npm run build-prod bundle.js 698 bytes

IIFE: ( var a = 10; function one() {

} function two() {

} )();

( var a = 50; function one() {

} function three() {

} )();

TypeScript

JS: var x = "Raj";

x = 10;

x = true;

first.ts ==> tsc [ check the types] ==> first.js [ JS engine]

Typescript types:

  1. Number let age:number = 30;

    age = "A"; // tsc throws error

  2. String

    let name:string = "Tim";

    name = 10; // tsc error

  3. Boolean let flag:boolean = true;

  4. arrays let elems:number[] = [6,3,7,2]; or

    let elems:Array = [5,2,5,7];

  5. enum

    enum Colors { RED, GREEN, BLUE };

    let clr:Colors = Colors.GREEN;

  6. any let data:any;

    data = doTask();

    data["name"] ; // can use it

  7. unknown let data:unknown;

    data = doTask();

    data["name"] ; // error

  8. 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"); }

function someTask(): never { throw new Error("some error!!!"); }

interfaces :

  1. 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());

tsc Product.ts

@Component({ selector: 'app-bank-account', template: Bank Name: {{ bankName }} Account Id: {{ id }} }) export class BankAccountComponent { }

@Component({ selector: 'app-product',

}) class Product{

}

https://codepen.io/

React.JS

Server side Rendering and Client side rendering

Rendering ==> data to presentation

Server side Rendering:

  1. Servlet and JSP
  2. ASP, ASP.NET
  3. PHP
  4. Flask
  5. JS: Pug, JADE, EJS

Client Side Rendering: server sends data; redniering is done on client machine [ payload ==> xml, json, csv]

  1. Templates Mustache, Handlebars, Underscore, jQuery templates

  2. View Library ( V part of MVC ) React.JS

  3. Framework ( Model View Controller) Angular, Backbone, Ember ========================================

    SPA ==> Single Page Applications

    1. handle multiple modules

    2. Data ==> Presentation

    3. 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?

      1. SEO
      2. Bookmark
      3. History API
    4. 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

Welcome to React 17

Learning Functional components

}

ReactDOM.render(, document.getElementById("app"))

props ==> mechanism using which parent component passes data to child component

// JSX function Welcome(props) { return

Welcome to {props.title}

{props.info}

}

ReactDOM.render(, document.getElementById("app"))

==========================

// JSX

function Welcome({title, info}) { return

Welcome to {title}

{info}

}

ReactDOM.render(, document.getElementById("app"))

Day 3:

==> 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

render()

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

Button ==> color; caption; size ==> state click, mousehover, keypress

npx create-react-app customerapp

Before: npm i -g create-react-app 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

"eject": "react-scripts eject" ==> scaffolding code ==> webpack.config.js

React props and state are keywords

any changes to props and state ==> react re-renders

Props: parent to child; keyword; immutable

Filter.js

Delete

OR

<button type="button" onClick={() => this.deleteRow()}>Delete

Testing React application:

JS Unit Testing Framework: Jasmine, Mocha, JEST

RTL ==> React Testing Library ==> built on JEST

RTL can be used as unit testing and integration testing

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

queryByXXXX() ==> returns element or null

queryByText() queryByPlacerHolderText('search by name') queryByAltText("logo"); 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

npx create-react-app phoneapp phoneapp>npm i bootstrap styled-components react-router-dom

Day 4:

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()

let {container} = render(); // access to DOM api

npx create-react-app phoneapp $phoneapp> npm i bootstrap styled-components react-router-dom

$ customerapp> npm i -D cypress @cypress/instrument-cra

Cypress ==> E2E testing / like Protractor for Angular / like Selenium

"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" }

place filter.spec.js and customer_delete.spec.js in "src"

Phoneapp Application:

  1. React-router-dom
  2. styled-components
  3. React Context [ React 16+ ]
  4. fontawesome , google fonts
  5. 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

bootstrap ==> CSS Library for Responsive Web Design page ==> different devices and resolution

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 SomeContext = React.createContext({"x": 10, "y": 15})

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>

} }

ReactDOM.render(, document.getElementById("app"));

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

  1. place "img" folder in "public"
  2. Replace "App.css" in src folder
  3. place "data.js" in src folder
  4. place "Button.js" in "components" folder
  5. Replace "Navbar.js" in "components" folder
  6. 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

Hello

Good Day

}

Solution: function App() { return

Hello

Good Day

}

Problem: we introducted extra

in HTML DOM or:

function App() { return <React.Fragment>

Hello

Good Day

</React.Fragment>

}

or: function App() { return <>

Hello

Good Day

</> }

Chrome webextension:

  1. React Developer Tools
  2. redux devtools

Task: complete CartList to display cart items and invoke context methods -> increment() decrement()