Banuprakash C
Full Stack Architect,
Co-founder & CTO, Lucida Technologies Pvt Ltd.,
Corporate Trainer,
Emails: banuprakashc@yahoo.co.in; banuprakash.cr@gmail.com
https://www.linkedin.com/in/banu-prakash-50416019/
https://github.com/BanuPrakash/JS
Softwares Required:
Visual Studio Code.
Chrome Web Browser
NodeJS Latest LTS
=======================
JS: loosely typed, dynamically typed, event driven programming language
var name = "Roger"; // string
var age = 23; // number age++; age = "Twenty Four"; // valid age++; // fails
ECMA JS needs JS engine for execution
- V8 -- Google --> Chrome / NodeJS
- SpiderMonkey --> Firefox
- Rhino --> oldest
- Nashorn --> Oracle
- Chakra --> IE11
- Continnum --> Edge
- IonMonkey
Internals of JS:
Context: Creation Context and Execution Context
var g = 100; // global variable
function doTask() {
var a = 10;
if(g > a) {
var b = 25;
c = 50;
console.log(g, a, b, c);
}
console.log(g, a, b, c);
}
doTask();
console.log(g, a, b, c);
Note: to avoid variables from hoisting globally and to avoid "this" pointer passing to function we use: "use strict";
==================
file.js
console.log("Hello");
setTimeout(function doTask() {
console.log("task 1");
}, 0);
setTimeout(function doAnotherTask() {
console.log("task 2");
}, 0);
Promise.resolve().then(function p1() {
console.log("p1");
});
Promise.resolve().then(function p2() {
console.log("p2");
});
console.log("Bye");
JS engines provides basic apis like String, Date, programming constructs
functions like setTimeout., Promise, ... are not provided by core JS engine rather they are provided by libraries like WebApi / Libuv
libuv is a multi-platform C library that provides support for asynchronous I/O based on event loops.
class TimerThread extends Thread {
TimerThread(int delay, Queue queue, Method m) {
...
}
public void run() {
Thread.sleep(delay);
queue.push(m);
}
}
Return type of a function is "undefined by default":
function hello() {
console.log("Hello");
}
hello();
function add(a, b) {
console.log(a + b);
}
let res = add(4,5); // undefined
function's are instances of Function extends Object
var sub = new Function("x", "y" , "return x - y")
======================
OOP in JS:
Different ways to create objects:
-
Object constructor var obj = new Object(); // add state obj.x = 10; obj.y = 15; obj.area = function() { return this.x * this.y; }
-
Functional Constructor pattern
2.1) class owned instance methods
function Product(name, price) {
this.name = name; //state
this.price = price; // state
}
// behaviour
Product.prototype.getPrice = function() {
return this.price;
}
// behaiour
Product.prototype.setPrice = function(p) {
this.price = p;
}
Product.prototype.getName = function() {
return this.name;
}
// static
Product.equals = function(p1, p2) {
return p1.name === p2.name;
}
var p1 = new Product("iPhone", 89000.00);
console.log(p1.getName(), p1.getPrice());
var p2 = new Product("Samsung", 89000.00);
if(Product.equals(p1, p2)) {
...
}
2.2) object owned instance methods
Avoid this X
function Product(name, price) {
this.name = name; //state
this.price = price; // state
this.getName = function() {
return this.name;
}
this.getPrice = function() {
return this.price;
}
}
- If Object is mostly used as data transfer object prefer JSON JavaScript Object notation
var product = {
"name" : "iPhone",
"price" : 89000.00,
"getName" : function () {
return this.name;
}
};
product.getName(); // iPhone
var ref = product.getName;
console.log(ref()); // gives name of window
Solution: var ref = product.getName.bind(product); console.log(ref());// iPhone
=========
function updateName(name) {
this.name = name;
}
var product = {
"name" : "iPhone",
"price" : 89000.00
}
var person = {
"name": "Peter",
"age" : 25
}
updateName.call(product, "Samsung");
updateName.call(person, "Sam");
Or
updateName.apply(product, ["Samsung"]);
HOF: high Order functions are
- functions which accept function as argument
- function which return function
Any execution which happens in Virtual environment like JVM / Java Script engine / MVM ; we create objects --> heap area; Garbage collectiors --> low priority thread are responsible for cleaning up un-used objects; Another reason why we can't use pointers in these languages
Short term GC --> for Eden Area / New Generation Long term GC --> Old Generation
filter --> subset map --> transform
Output of :
function add(a, b) {
return
a + b;
}
let res = add(4,5); // undefined
function which return function: closure
function adder(base) {
return function(no) {
return base + no;
}
}
var fiveAdder = adder(5);
fiveAdder(2); //7
fiveAdder(3); //8
==================================
ECMA --> JavaScript Specification; versioning
Most of the Browsers support ESMAScript5 --> JS 5
ES 6 --> ECMAScript 6 --> ECMAScript2015
ES 6 features: https://caniuse.com/
Babel Babel is a free and open-source JavaScript transcompiler that is mainly used to convert ECMAScript 2015+ code into backwards-compatible JavaScript code that can be run by older JavaScript engines. Tracuer
Features:
- new template string: tick; can have multiline string; variable interpolation
<div class="card"> <div class='card-header'> ${e.name} </div> <div class='card-body'> ${e.price}, ${e.category} </div> </div>
- scope variables and constants using "let" and "const"
const PI = 3.14159;
var g = 100; // global variable
function doTask() {
var a = 10;
if(g > a) {
let b = 25;
console.log(g, a, b);
}
console.log(g, a, b); // b is not visible here
}
doTask();
Code in ES 6 might look like:
var g = 100; // global variable
function doTask() {
var a = 10;
if(g > a) {
var _ref = (
var b = 25;
return {
b: b
}
)();
console.log(g, a, _ref.b);
}
console.log(g, a, b); // b is not visible here
}
doTask();
IIFE --> Immediate Invoke Function Expression ()(); Module system to introduce the concept of visibility in JS
var ShopModule = (
var data = ....
function add() { ...}
function computeTotal() {...}
return {
add,
data
}
)();
ShopModule.data;
ShopModule.add(...)
ShopModule.computeTotal(); // error
var CustomerModule = (
var data = ....
function add() { ...}
function delete() {...}
return {
add,
data,
delete
}
)();
CustomerModule.data
CustomerModule.add()
CustomerModule.delete()
- Destructuring and Rest operators 3.1) Objects var product = {"id": 523, "name": "Oppo", "price": 15000.00, "category": "mobile"}; Traditional way: console.log(product.name, product.price);
ES 6 way:
let {name,price} = product; console.log(name, price);
3.2) array let colors = ["red", "green", "blue", "orange", "pink"]; Traditional way: console.log(colors[0], colors[1]);
ES 6 way:
let [r,g,...others] = colors; console.log(r, g); // red, green
//others ["blue", "orange", "pink"];]
var myMod = ( function() { var data = 10; return { data } } )(); myMod.data;
- Spread operator to add var products = [ {"id": 523, "name": "Oppo", "price": 15000.00, "category": "mobile"}, {"id": 86, "name": "Onida", "price": 12000.00, "category": "tv"}, {"id": 523, "name": "iPhone", "price": 95000.00, "category": "mobile"}, {"id": 523, "name": "Samsung OLED", "price": 315000.00, "category": "tv"}, {"id": 523, "name": "Wacom", "price": 4000.00, "category": "computer"}, {"id": 523, "name": "Nothing", "price": 12000.00, "category": "mobile"} ];
var data = [...products, {"id": 4, "name": "A", "price": 222}]; https://immutable-js.com/ https://immerjs.github.io/immer/
var p = {"id": 523, "name": "Oppo", "price": 15000.00, "category": "mobile"};
let ref = p; // reference ref.price = 100;
console.log(p.price); // 100
let clone = {...p}; // clone clone.price = 9999;
console.log(p.price); //100
================
- Promise for exeuting asynchronous operations
getConnection().then( con => getProjects(con) .then(projects => getEmployees(projects) .then(employees => getEmails()) .then(email => sendEmail(..)) )
WebApi: Promise, setTimeout, setInterval
===========
Recap:
- JS engine, Stack, WebApi / Libuv, CallbackQueue [Micro Task Queue, Macro Task Queue], Event Loop
- OOP : Object, functional cosntructor , JSON
- call, apply and bind methods of Functional Object
- HOF: forEach, filter, map, Closure
- ES 6 features
- new template string literal using ticks ``
- let and const --> block level scope
- Destructuring
- Spread operators ...
- Promise
- Async and Await
- arrow function let add = (x, y) => x + y;
- ES6 Module 9 ) class class Product {}
let p = new Product(); 10) generator 11) Proxy
Promise is an object which can have one of these states a) pending b) fulfilled c) rejected
When a new Promise object is created and called it's in pending state; generatlly within promise we write some async operations like fetching data from a resouce like server/ file system
Promise has static methods resolve() and reject()
thenable:
Promise.resolve("Product added").then( function(output) {
// fulfilled code
},
function (err) {
// rejected code
});
function doTask() {
return new Proomise(function (res, rej) {
// do some job which could be async operations like fetch from server
// based on status code from server 200 or 404 or 403 or 500
res("data from server");
//or
rej("error message")
});
}
doTask().then( function(output) {
// fulfilled code
},
function (err) {
// rejected code
}).catch(ex) {
}. finally {
};
catch block
===================================
Day 2
DOM and NodeJS, Webpack
DOM: Document Object Model --> when we have XML [XHMTL] --> in the form of Object tree is DOM; DOM is an interface; object can be Java / JS / VB Script
- access DOM elements --> getElementById() --> single element --> getElementsByTagName() --> array of elements document.getElementsByTagName("div"); --> querySelector() --> querySelectorAll() uses CSS Selectors
document.querySelectorAll("div"); // by Tag Name document.querySelectorAll(".card"); // by class name
document.querySelector("#btn"); // by ID
document.querySelectorAll("input");document.querySelector("input[placeholder='search by name'");
- create new DOM elements
document.createElement() is a factory method to create DOM elements document.createElement("button") document.createElement("table")
- remove
- add event handling
https://opentdb.com/api.php?amount=10
Event Handling:
based on Observer Observable design pattern
ALL DOM elements are Observable
DOM elements generate various events like click, mousemove, change, keypress, ... focus, blur.
let event = new Event("myevent");
document.dispatchEvent(event);
let event = new CustomEvent("add-user", {});
============
NodeJS Platform built on top of V8 JS engine and Libuv libraries for Async support like execution of Promise / interval / netwrok similar to what WebApi provided
Why nodejs?
-
build Traditional Web applications like Servlets / PHP / ASP.NET / Django .
-
build RESTful WS
-
GraphQL
-
Streaming platform
-
ChatBot
-
Client side web application development
Challenges while building Client side web application development:
- We can choose to write the code in TypeScript, CoffeeScript, LiveScript, DART or latest version of JS
let name:string = "Tim"; name = 44; // error
- Unit testing
- Integration testing
- E2E testing
- Static Code analysis
- Minify and Uglify the code
function _d(){var a = 10;if(g > a) {var _ref = (var b = 25;return {b: b})();
_d()
- bundle Customer.js Product.js Order.js Payment.js .... => minimum of 50+ js modules will be there
instead:
<script src="bundle.js"> </script>How does a node project looks like?
package.json --> like pom.xml file where we configure depenencies reqired for the project, script
node_modules
*.js
=== create a NodeJs Project:
npm init --y
npm --> node package manager comes by default with NodeJS installation --> used to download dependencies, run scripts, publish yarn , PNPM ,RUSH, lerna, ... alternate
npm install lodash or npm i lodash
"lodash": "4.17.21" --> exact version
"lodash": "^4.17.21" --> any latest version >= 4.17.21
"lodash": "~4.17.21" --> major version has to be "4", minor and patch can latest
npm i jest -D
================
JS Module System:
-
IIFE
-
CommonJS module System --> default used by nodejs module.exports and require ---> import
-
ESM --> ECMAScript Module
-
AMD --> Asynchronous Module Defintion
-
SystemJS
=============
JS Unit testing Frameworks:
- Jasmine [ good for web] --> default for Angular developers
- Mocha [good for server side api]
- Jest [ good for web] --> default react developers
AAA ==> Assemble Action Assert
"scripts": { "test": "jest" },
Code Coverage: jest --coverage
================================
JS build tools:
- Grunt
- Gulp
- Webpack
- vite
Grunt is a JavaScript task runner, a tool used to automatically perform frequent tasks such as minification, compilation, unit testing, and linting. It uses a command-line interface to run custom tasks defined in a file
=======
-
webpack-basic> npm init --y
-
install dependencies:
npm i webpack webpack-cli css-loader style-loader html-webpack-plugin clean-webpack-plugin babel-loader @babel/core @babel/preset-env -D
Babel is a free and open-source JavaScript transcompiler that is mainly used to convert ECMAScript 2015+ code into backwards-compatible JavaScript code that can be run by older JavaScript engines.
ECMAScript 2015+ ---> ES 5 target
Babel supports ES 6 /ECMAScript 2015+ module system
instead of let {forEach, filter, map} = require('./lib');
we use
import {forEach, filter, map} from './lib'
import 'logo.png' ===> file-loader
import './styles.css' --> css-loader
babel-loader @babel/core @babel/preset-env
import {forEach, filter, map} from './lib' ===> babel-loader gives the loaded file to @babel/core ==> Compiler / Transcompiler
@babel/preset-env
- Syntax transform
- polyfills
@babel/preset-env is a smart preset that allows you to use the latest JavaScript without needing to micromanage which syntax transforms (and optionally, browser polyfills) are needed by your target environment(s)
https://www.npmjs.com/package/core-js
======
babel.config.js or .babelrc or babel.config.json
module.exports = {
presets: [
'@babel/preset-env'
]
}
npm run dev
webpack-basic@1.0.0 dev webpack --mode development
asset bundle.f8b2bc99.js 8.87 KiB [emitted] [immutable] (name: main) runtime modules 670 bytes 3 modules cacheable modules 3.83 KiB ./src/index.js 1.31 KiB [built] [code generated] ./src/lib.js 496 bytes [built] [code generated] ./src/Person.js 2.04 KiB [built] [code generated] webpack 5.93.0 compiled successfully in 389 ms
npm run prod
webpack-basic@1.0.0 prod webpack --mode production
asset bundle.7e4a25af.js 2.32 KiB [emitted] [immutable] [minimized] (name: main) orphan modules 2.53 KiB [orphan] 2 modules ./src/index.js + 2 modules 3.83 KiB [built] [code generated] webpack 5.93.0 compiled successfully in 397 ms
npm i webpack-dev-server -D
npm start
npm test
npm run prod npm run dev
==============
Recap:
DOM NodeJS: package.json, node_modules
only executable dependencies can be kept global /users/<>
below command will download all depdencies configured in package.json npm install or npm i
webpack: java script build tool to automate --> compiler, unit testing, linting, bundle, ...
- babel.config.js --> configure presets
- webpack.config.js --> entry, output, rules for loaders, ....
===
Day 3 : React
Client side rendering
- Web application --> JS
- DOM
- jQuery library simplified DOM usage
$("div") --> document.querySelectorAll("div"); $("
XmlHttpRequest to make API calls $.getJSON()
- Templates
3.1) Underscore 3.2) jquery template 3.3) Mustache 3.4) Handlebars 3.5) PUG 3.6) JADE 3.7) Knockout ....
Handlebars Example:
Data:
{
people: [
"Yehuda Katz",
"Alan Johnson",
"Charles Jolley",
],
}
Template:
<ul class="people_list">
{{#each people}}
<li>{{this}}</li>
{{/each}}
</ul>
Output:
<ul class="people_list">
<li>Yehuda Katz</li>
<li>Alan Johnson</li>
<li>Charles Jolley</li>
</ul>
- Single Page Applications --> SPA MVC Architecture Model View Controller
4.1) Backbone library: they gave Model and Controller support; for view we could pick any of the above templates
4.2) AngularJS framework: MVC --> Google
4.3) ReactJS story marcel laverdet facebook 2010 --> XHP; facebook was developed using PHP 2011 --> FaxJS --> Jorde Walk ~2014 --> React OpenSource --> Sophie Alpert --> Khan's Academy
======
React: Babel --> @babel/preset-react
npm i @babel/preset-react -D
JSX
https://github.com/chentsulin/awesome-react-renderer
==============
create-react-app ==> scaffolding code built using webpack, adds React and react-dom libraries
Old versions: npm i create-react-app -g create-react-app usersapp
New: npx create-react-app usersapp
Thinking in React:
- Atom Button, Label, Image, Input, .... Re-usable components
- Molecule
- Organism
- Template
- Page
React Components:
- React.createElement
- Functional components is a js function which returns JSX
- Class Component --> inherit from Component / PureComponent and override render() method render() -> returns JSX
Class Component: can have state and behaviour
Each child in a list should have a unique "key" prop. https://legacy.reactjs.org/docs/reconciliation.html
App.js
<Ingredient ... />
===============================
Testing:
- Unit testing
- Integration testing
- E2E testing
RTL: React Testing library is built on top jest
getByRole .. screen.getByRole('button') screen.getAllByRole('button')
getByPlaceholderText screen.getByPlaceHolderText('search by name');
getByText screen.queryByText(/Users Application/);
getByAltText
=====================
E2E testing npm i cypress -D package.json "e2e": "cypress open"
server should be running npm start another terminal: npm run e2e
Day 4
@babel/preset-react JSX --> JS object react library uses this React --> createElement()
Rendering ==> state --> Presentation react-dom react-native react-tv proton --> Desktop
JS object ---> VDOM, any changes done will be for copy of VDOM Diff algorithm --> to identify what got changed --> update the actual DOM
class component : state and behaviour
state = { x: 10, y: 15 }
============
class Component Life Cycle:
Mounting Phase: when first time component is created
constructor() ==> render() ==> componentDidMount()
intialization ==> render() ==> Make API calls and update the state
product: [..] ==> render() with dummy data ==> get products from API call and update the products; triggers re-rendering
making API call in constructor() leads to FCP web vitals issue First Contentful Paint
Updating Phase: whenever state/props changes --> forces reconcilliation --> re-rendering
shouldComponentUpdate() --> render() --> componentDidUpdate() componentDidUpdate() --> Make depdendent API calls
UnMounting Phase: when component is destroyed --> componentWillUnMount() suppose we have subscribed for notifications; we should unsubscribe in componentWillUnMount()
==========
stackblitz, codepen, ...
codepen --> Settings
- JavaScript Preprocessor: Babel
- https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/cjs/react.production.min.js [not Working] https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js [ working]
- https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/cjs/react-dom.production.min.js https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js [working]
Behaviour:
- off Auto-save and Auto-preview
Example for shouldComponentUpdate()
class ParentComponent extends React.Component {
state = {
name : "Roger",
age : 34
}
changeAge() {
this.setState( {
age: this.state.age + 1
})
}
changeName() {
this.setState( {
name: this.state.name + "..."
})
}
render() {
console.log("Parent renders")
return <div>
<NameComponent name = {this.state.name} /> <br />
<AgeComponent age = {this.state.age} /> <br />
<button type="button" onClick={() => this.changeAge()}>Change Age </button>
<button type="button" onClick={() => this.changeName()}>Change Name </button>
</div>
}
}
class NameComponent extends React.Component {
shouldComponentUpdate(prevProps, prevState) {
if(this.props.name === prevProps.name) {
return false;
}
return true;
}
render() {
console.log("NameComponent renders")
return <div>
Name Component : {this.props.name}
</div>
}
}
class AgeComponent extends React.Component {
shouldComponentUpdate(prevProps, prevState) {
if(this.props.age === prevProps.age) {
return false;
}
return true;
}
render() {
console.log("AgeComponent renders")
return <div>
Age Component : {this.props.age}
</div>
}
}
ReactDOM.render(<ParentComponent />, document.getElementById("root"));
Memoization:
function memo(Component) {
var propsCache = {};
if( newpros compare with propsCache) {
if same
return;
}
return Component(props);
}
Memoization of Functional Component:
class ParentComponent extends React.Component {
state = {
name : "Roger",
age : 34
}
changeAge() {
this.setState( {
age: this.state.age + 1
})
}
changeName() {
this.setState( {
name: this.state.name + "..."
})
}
render() {
console.log("Parent renders")
return <div>
<MemoNameComponent name = {this.state.name} /> <br />
<MemoAgeComponent age = {this.state.age} /> <br />
<button type="button" onClick={() => this.changeAge()}>Change Age </button>
<button type="button" onClick={() => this.changeName()}>Change Name </button>
</div>
}
}
let MemoNameComponent = React.memo(NameComponent);
let MemoAgeComponent = React.memo(AgeComponent);
function NameComponent({name}){
console.log("NameComponent renders")
return <div>
Name Component : {name}
</div>
}
function AgeComponent(props){
console.log("AgeComponent renders")
return <div>
Age Component : {props.age}
</div>
}
ReactDOM.render(<ParentComponent />, document.getElementById("root"));
Context provides a way to pass data through the component tree without having to pass props down manually at every level.
let userContext = new Context("avatar": window.localStorage("pic"))
Context Example:
let UserContext = React.createContext();
class ParentComponent extends React.Component {
state = {
name : "Roger",
age : 34
}
changeAge() {
this.setState( {
age: this.state.age + 1
})
}
render() {
return <UserContext.Provider value={{name:this.state.name, age: this.state.age}}>
<A />
<button type="button" onClick={() => this.changeAge()}>Change Age </button>
</UserContext.Provider>
}
}
class A extends React.Component {
render() {
return <B />
}
}
class B extends React.Component {
render() {
return <div>
<UserContext.Consumer>
{
value => {
return <div> Name : {value.name}, Age: {value.age} </div>
}
}
</UserContext.Consumer>
</div>
}
}
ReactDOM.render(<ParentComponent />, document.getElementById("root"));
Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class.
Consumers in functional Component: <UserContext.Consumer> is valid alternatively we have a hook called useContext() useContext() is for Context Consumer can be used only in functional components React 16.8 versions introduced hooks for functional components
function B() {
let {name, age} = React.useContext(UserContext); // consumer
return <div>
Name : {name}, Age: {age}
</div>
}
Class Components: state, life cycle methods
Angular: @Component({ "template":
}
React:
public class ProductComponent extends Component{
}
React Hooks:
-
useState
-
useEffect
-
useContext
-
useReducer
-
useMemo
-
useCallback
-
useState hook is used to introduce state in functional component
function ParentComponent() {
let [name, setName] = React.useState("");
let [age, setAge] = React.useState(18);
return <div>
Name: {name} <br />
Age: {age} <br />
<button type="button" onClick={() => setAge(age + 1)}>Change Age </button>
</div>
}
- useEffect is a hook to introduce component life cycle methods in functional component
function SampleComponent {
// same as componentDidMount
useEffect(() => {
...
return () => console.log("unmount"); <-- similar to componentWillUnMount
}, []);
// similar to componentDidUpdate
useEffect(() => {
...
});
// gets called when name changes
useEffect(() => {
...
}, [name]);
}
npx create-react-app hooksdemo npm i bootstrap
====================
Rules of Hooks:
- can't use it in class components
- use it at the top level of functional components
- can't use it inside event handlers/ conditional statement /try-catch
- one hook can use another hook(s)
useReducer() hook should be used instead of useState() if mutation depends on previous state and conditionally mutate the state
{
cartItems: [{},{}],
total: computed,
quantity: 0
}
Action Objects:
{
type:'type_of_action',
payload?: <body>
}
Example:
{
type:'ADD_TO_CART',
payload: product
}
{
type:'CLEAR_CART'
}
{
type: 'INREMENT',
payload: pid
}
Reducer function: (state, action) => new state
let [state, dispatch] = useReducer(reducerFn, initialState);
dispatch is used to delegate action to reducer function
{ type: 'INCREMENT', payload: 10 }
{ type: 'DECREMENT' }
{ type: 'REST' }
==========
https://fakestoreapi.com/products?limit=5
- react-router-dom --> different URLs different views has to be rendered http://localhost:3000/products http://localhost:3000/details/4 http://localhost:3000/cart http://localhost:3000/new_product
--> Lazy loading of components generally webpack --> creates a single bundle --> bundle.js
-
hooks
-
Context
-
reducers
-
bootstrap, react-bootstrap / Adobe React Spectrum and Adobe webcomponents https://www.telerik.com/kendo-react-ui/components/ https://primereact.org/
-
font-awesome --> icons
<NavbarComponent />
<ProductList />
<ProductCard />
<Details />
<CartComponent />
<CartList />
<ProductForm />
<Default />
=============
boostrap --> CSS Framework for RWD using boostrap:
using react-bootstrap
npx create-react-app productsapp
cd productsapp productapp>
npm i react-router-dom bootstrap react-bootstrap @fortawesome/react-fontawesome @fortawesome/free-solid-svg-icons
======
https://ionicframework.com/docs/api/router
===================
href ==> Server Side Routing ==> whole page reloads link ==> Client side Routing
==========
Day 5
Recap:
- Context
props thro component tree
Provider --> places data into context [value] Consumer --> can access data from Context [ Observer], useContext
- React Hooks a) useState() b) useEffect() c) useContext() d) useReducer() --> to be used instead of useState() if state mutation depends on previous state & conditiionally mutate the state
reducerFn ==> (state, action) => new state
react-router-dom ==> BrowserRouter
================================================= instead of fetch: npm i axios
Chrome Web store: add extensions:
- react development tools
- redux dev tools
files: cartReducer.js CartProvuder.jsx index.js ProductCard.jsx NavbarComponent.jsx
=================
JSON-SERVER : Get a full fake REST API with zero coding in less than 30 seconds
npx json-server --watch data.json --port 1234 Endpoints: http://localhost:1234/customers http://localhost:1234/orders http://localhost:1234/products
==========
Assume on successful login; user data is stored in client machine sessionStorage window.sessionStorage.setItem("user","banu@gmail.com")
data.json ProductProvider.jsx index.jsx CartProvider.jsx ProductList.jsx
=========================================
- Uncontrolled components
- Controlled components
Example of Controlled components: react holds the state of component<> at any given point of time
function Controlled() {
let [name,setName] = useState("");
let [age, setAge] = useState(18);
function doSubmit() {
axois.post(...)
}
return <form>
Name: <input type="text" onChange={evt => setName(evt.target.value)} /> <br />
Age: <input type="text" onChange={evt => setAge(+evt.target.value)} /> <br />
<button type="submit" onClick={doSubmit}>Add</button>
</form>
}
Example of Uncontrolled Components:
function Controlled() {
let nameRef = useRef();
let ageRef = useRef();
function doSubmit() {
let name = nameRef.current.value;
let age = ageRef.current.value;
}
return <form>
Name: <input type="text" ref={nameRef}/> <br />
Age: <input type="text" ref={ageRef} /> <br />
<button type="submit" onClick={doSubmit}>Add</button>
</form>
}
npm i @adobe/react-spectrum yarn add @adobe/react-spectrum
https://opensource.adobe.com/spectrum-web-components/using-swc-react/
npm i @swc-react/card
Context "questions" : [], // includes options, correct-option "answers": { 1: 4, 2: 5, 3: 5 }, "correct" : 4 "attempted": 5
https://opentdb.com/api.php?amount=10
Replace Quote: str = str.replace(/<script[^>]>([\S\s]?)</script>/gmi, ''); str = str.replace(/</?\w(?:[^"'>]|"[^"]"|'[^']')*>/gmi, '');
Recap of day 5:
- Context: Anti-pattern for state management [ state and behaviour], why React create Context was just to avoid props-drill Provider, Consumer, useContext
- Form handling:
- Controlled Components using useState()
- un-controlled components using useRef()
- Adobe react spectrum and using Adobe webcomponents [ developed using lite]
@swc/button, @swc/card <-- react wrappers for lite component
===============
Day 6
MVC Architectural pattern was used by Facebook, which had lots of issues https://www.infoq.com/news/2014/05/facebook-mvc-flux/ https://www.youtube.com/watch?v=8pDqJVdNa44
EventEmitter
class AppStore extends EventEmitter { .. }
Predictable State Managment libraries:
- Flux by Facebook
- Redux by Dan Abramov
- Mobx
- Zustand
- Recoil
- ObservableRx
Context vs Redux
Context:
- not designed for state management, anti-pattern to do state management Context provides a way to pass data through the component tree without having to pass props down manually at every level.
- good for small sized application
- tightly coupled to react
- can't do time-travel debugging
Predictable State Managment libraries
- good for large applications
- can be developed as a seperate module and can be integrated into View frameworks like react, angular, jQuery, JS or even server side code ExpressJS, or any other nodejs modules
- time-travel-debugging
- good for Micro-frontend --> evolving technologies
Redux State Management
-
Store --> A Single store per redux application
-
State is present in store { "cart": { cartItems: [...], total: 2554 }, "profile": { avatar : "banu.png", "displayName": "Banu" } }
-
reducers: are functions which take action & state, mutate the state and return back new state
cartReducer profileReducer orderReducer
- root-reducer
connect(
mapStateToProps,mapDispatchToProps
)(App)
function mapDispatchToProps(dispatch) {
return {
addToCart: item => dispatch({type:'ADD_TO_CART', payload: item}),
clearCart: () => dispatcy({type:'CLEAR_CART'})
}
}
Legacy Redux ContactsManager
ADD_CONTACT REMOVE_CONTACT CLEAR_CONTACTS
npx create-react-app contacts-manager contacts-manager> npm i redux react-redux
App or any of it's children can access redux store
<Provider store={store}>
<App />
</Provider>
Why Clone collections? https://immutable-js.com/ https://immerjs.github.io/immer/
state
==================== https://redux-toolkit.js.org/ @reduxjs/toolkit instead of redux
Convert productapp to use Reduxtoolkit instead of Context
Step 1: productapp-rtk % npm i @reduxjs/toolkit react-redux
npx json-server --watch data.json --port 1234
Step 2: delete CartContext a) CartProvider.jsx b) reference in index.js c) ProductCard.jsx d) NavbarComponent.jsx f) CartComponent.jsx g) CartList.jsx f) delete reducers folder
actions
reducer
clone
const slice = createSlice({
name: 'test',
initialState: 0,
reducers: {
increment: (state, action) => state + action.payload,
decrement: (state) => state - 1,
reset: state => 0
},
})
// now available:
slice.actions.increment(2)
slice.actions.decrement()
slice.actions.reset()
{ "cart": { cartItems: [], total: 0, quantity: 0 }, "profile": { avatar : "banu.png", displayName : "Banuprakash" } }
Redux react hooks: no need for connect() HOC
- useSelector() The selector is approximately equivalent to the mapStateToProps argument to connect conceptually.
- useDispatch() is approximately equivalent to the mapDispatchToProps argument to connect conceptually.
Redux triggered @@INIT action and initilizes all the reducers [ provided by cartSlice] and state is created