SlideShare a Scribd company logo
1 of 138
Download to read offline
Babel Coder
RECAP JAVASCRIPT
Babel Coder
TEMPLATE
Template String
var myStr1 = 'Hello World'
var myStr2 = "Hello World"
var myStr3 = "HellonWorld"
var myStr4 = `
Lorem ipsum dolor sit amet,
consectetur adipiscing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
`
var myStr5 = `${myStr1} Krub`
Babel Coder
LET AND CONST
function foo() {
let x = 1
x = 2
}
foo()
function foo() {
const x = 1
x = 2
}
foo()
Babel Coder
PROPERTY SHORTHAND
const x = 10
const y = 20
const obj = { x: x, y: y }
const obj = { x, y } Property Shorthand (ES6+)
Babel Coder
DESTRUCTURING
let person = {
age: 24,
gender: 'male',
name: {
fi
rstName: '
fi
rstName',
lastName: 'lastName'
}
}
let age = person.age
let gender = person.gender
let name = person.name
let
fi
rstName = name.
fi
rstName
let lastName = name.lastName
let { age, gender, name } = person
let {
fi
rstName, lastName } = name
let { age, gender, name: {
fi
rstName, lastName } } = person
Babel Coder
SPREAD OPERATORS
const obj1 = { a: 1, b: 2 }
const obj2 = { c: 3, d: 4 }
console.log({ ...obj1, ...obj2 })
const arr1 = [1, 2, 3]
const arr2 = [4, 5, 6]
console.log([...arr1, ...arr2])
Babel Coder
EXAMPLE 1
Math.min(12, 14, 8, 17, 21, 9) // 8
const nums = [12, 14, 8, 17, 21, 9]
Math.min(...nums)
Babel Coder
ARROW FUNCTION
function foo(a) {
return a + 1
}
const foo = (a) => {
return a + 1
}
const foo = a => {
return a + 1
}
const foo = a => a + 1
const foo = a => let b = a + 1 Must be expression
OPTIONAL CHAINING
const person = {
name: 'Somchai',
age: 24,
socials: {
facebook: 'somchai24'
}
}
<div>
<div>{person?.socials?.facebook}</div>
</div>
<div>
<div>{person?.tel?.phone}</div>
</div>
ES MODULE - NAMED EXPORTS
export const DEFAULT_COLOR = 'white'
export function walk() {
console.log('Walking...')
}
{
DEFAULT_COLOR: 'white',
walk() {
console.log('Walking...')
}
}
dog.js
main.js
syntax: 1
import * as lib from './dog.js'
lib.DEFAULT_COLOR // white
lib.walk() // Walking...
main.js
syntax: 2
import { DEFAULT_COLOR, walk } from './dog.js'
ES MODULE - DEFAULT EXPORT
circle.js
main.js
syntax
export default class Circle {
area() {
}
}
import Circle from './circle.js'
ES MODULE - BOTH
circle.js
export const PI = 3.14
export default class Circle {
area() {
}
}
main.js
syntax
import Circle, { PI } from './circle.js'
Babel Coder
FETCHING
fetch('/api/v1/articles/1', function(response) {
fetch('/api/v1/users/' + response.authorId, function(response) {
// ...
})
})
fetch('/api/v1/articles/1')
.then(function(response) {
return fetch('/api/v1/users/' + response.authorId)
})
.then(function() { })
Babel Coder
AXIOS
import axios from 'axios'
axios.get('/articles')
.then(res => console.log(res.data))
axios.post('/articles', { title: 'Title#1', content: 'Content#1' })
.then(res => console.log(res.data))
GET
POST
Babel Coder
AXIOS BASE URL AND INTERCEPTORS
axios.defaults.baseURL = 'https://api.example.com'
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN
// Interceptors
axios.interceptors.response.use(
response => response,
error => {
if (error.response.status === 401) {
auth.clearAuth()
router.replace('/signin')
}
return Promise.reject(error.response)
}
)
ASYNC / AWAIT
promise.then(function(result) {
console.log(result)
}).catch(function(error) {
console.log(error)
})
async function doAsync() {
try {
const result = await promise
console.log(result)
} catch(error) {
console.log(error)
}
}
EXAMPLE 1
Fetch content from URL: https://jsonplaceholder.typicode.com/todos
import axios from 'axios'
async function fetchPosts() {
const res =await axios.get(URL)
console.log(res.data)
console.log(res.status) // 200
}
fetchPosts()
HTTP GET HTTP POST
import axios from 'axios'
async function createPost() {
const res =await axios.post(
URL, { title: 'Test', completed: true })
console.log(res.status) // 201
}
createPost()
WHAT IS FUNCTIONAL PROGRAMMING
• Functional Programming is a programming paradigm.
• It treats computation as the evaluation of mathematical functions.
• Avoid changing state.
• Eliminating side effects of function calls.
• Declarative Style
IMMUTABILITY
const nums = [1, 2, 3]
const nums2 = [6, 7]
nums.concat()
nums.slice()
nums.concat(4) // [1, 2, 3, 4]
nums.slice(0, 2); // [1, 2]
[...nums, 4, ...nums2]
// [1, 2, 3, 4, 6, 7]
const object = { a: 1, b: 2 }
// {"a":1,"b":2,"c":3,"d":4}
console.log({...object, c: 3, d: 4 })
// {"a":1,"b":9}
const newObject = { b: 9 }
console.log({ ...object, ...newObject })
// {"a":1,"b":9}
const key = 'b'
console.log({ ...object, [key]: 9})
1
MAP
const nums = [1, 2, 3]
console.log(nums.map(num => num * 2)) //
[2, 4, 6]
const students = [
{ id: 1, advisorId: 1 },
{ id: 2, advisorId: 2 },
{ id: 3, advisorId: 3 },
{ id: 4, advisorId: 1 },
{ id: 5, advisorId: 3 }
]
console.log(
students.map(student =>
student.advisorId === 1 ?
{ ...student, advisorId: 2 } :
student
)
)
// [{"id":1,"advisorId":2},
{"id":2,"advisorId":2}, {"id":3,"advisorId":3},
{"id":4,"advisorId":2}, {"id":5,"advisorId":3}]
2
FILTER
const students = [
{ id: 1, advisorId: 1 },
{ id: 2, advisorId: 2 },
{ id: 3, advisorId: 3 },
{ id: 4, advisorId: 1 },
{ id: 5, advisorId: 3 }
]
console.log(
students.filter(student => student.advisorId === 1)
)
// [{"id":1,"advisorId":1},{"id":4,"advisorId":1}]
3
FIND / FIND INDEX
const nums = [1, 2, 3, 4, 5]
nums.find(num => num % 2 === 0) // 2
const nums = [1, 2, 3, 4, 5]
nums.findIndex(num => num % 2 === 0) // 1
4
Babel Coder
INTRODUCTION TO
TYPESCRIPT
Babel Coder
SETUP
1 yarn init -y
2 yarn add -D tsc nodemon ts-node typescript eslint eslint-con g-prettier eslint-plugin-prettier prettier
@typescript-eslint/parser @typescript-eslint/eslint-plugin
3 npx tsc —init
4 package.json
"scripts": {
"dev": "nodemon src/index.ts",
"build": "tsc",
"lint": "eslint '*/**/*.{js,ts}' --quiet --
fi
x"
},
Babel Coder
SETUP
5 .eslintrc.js
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
},
settings: {},
extends: [
'plugin:@typescript-eslint/recommended',
'prettier/@typescript-eslint',
'plugin:prettier/recommended',
],
rules: {},
};
6 .vscode/settings.json
{
"editor.tabSize": 2,
"editor.codeActionsOnSave": {
"source.
fi
xAll.eslint": true
}
}
Babel Coder
SETUP
7 .prettierrc
{
"trailingComma": "all",
"singleQuote": true
}
8 nodemon.json
{
"watch": ["src"],
"ext": "ts",
"exec": "ts-node"
}
9 tscon
fi
g.json
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"lib": ["ES2020", "DOM"],
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
Babel Coder
SETUP
Babel Coder
PRIMITIVE DATA TYPES
• string
• number
• bigint
• boolean
• null
• undefined
• symbol
Babel Coder
PRIMITIVE DATA TYPES
const num1: number = 10
const num2 = 20
const bool1: boolean = true
const bool2 = false
const str1: string = "hello"
const str2 = "world"
Babel Coder
ANY AND UNKNOWN
function next(num: number) {
return num + 1;
}
let num: any = 10;
num = 'hello';
next(num);
num.toFixed(2);
let num: unknown = 10;
num = 'hello';
// Argument of type 'unknown' is not assignable to parameter of type 'number'.
next(num);
// Object is of type 'unknown'.
num.toFixed(2);
const num: unknown = 10;
next(num);
if (typeof num === 'number') {
next(num);
}
Babel Coder
LITERAL TYPES
let str1: 'Hello' = 'Hello';
let str2: string = str1;
// Type 'string' is not assignable to type '"Hello"'.
str1 = str2;
let str1 = 'Hello'; // string
const str2 = 'Hello'; // Hello
function permission(role: 'Admin' | 'Moderator' | 'Editor') {
// do sth
}
permission('Admin');
let role = 'Editor';
// Argument of type 'string' is not assignable
// to parameter of type '"Admin" | "Moderator" | "Editor"'.
permission(role);
permission(role as 'Editor');
Babel Coder
ARRAY
let nums1: number[] = [1, 2, 3] // number[]
let nums2: Array<number> = [1, 2, 3] // number[]
let nums3 = [1, 2, 3] // number[]
const nums4 = [1, 2, 3] // number[]
const nums5: readonly number[] = [1, 2, 3] // readonly number[]
const nums6: ReadonlyArray<number> = [1, 2, 3] // readonly number[]
const nums7 = nums6 as number[]; // number[]
const foo: string[] = []; // OK
const a: never[] = []; // OK
const b: never[] = [1, 2]; // Type 'number' is not assignable to type 'never'
Babel Coder
ENUM
enum Role {
Admin,
Moderator,
Editor,
}
const myRole: Role = Role.Admin; // 0
Role[0]; // Admin
Role.Admin // 0
enum Role {
Admin,
Moderator,
Editor,
}
enum Role {
Admin = 'Admin',
Moderator = 'Moderator',
Editor = 'Editor',
}
Role.Admin; // Admin
Babel Coder
INTERFACES
let person; // any
person = {
name: 'Somchai',
age: 24,
gender: 'male',
};
interface Person {
name: string;
age: number;
gender: string;
}
let person: Person;
person = {
name: 'Somchai',
age: 24,
gender: 'male',
};
// Property 'gender' is missing in type
// ‘{ name: string; age: number; }'
// but required in type 'Person'.
const person: Person = {
name: 'Somchai',
age: 24,
};
const person: Person = {
name: 'Somchai',
age: 24,
gender: 'male',
};
Babel Coder
EXTENDING INTERFACES
interface Website {
url: string;
}
interface Article {
title: string;
content: string;
}
interface BlogPost extends Website, Article {
view: number;
}
const post: BlogPost = {
url: 'https://www.babelcoder.com/blog/articles/typescript-classes',
title: 'การใ
ช้
งานคลาสใน TypeScript',
content: '...',
view: 999,
};
Babel Coder
READONLY AND OPTIONAL PROPERTIES
interface Person {
fi
rstName: string;
lastName: string;
middleName?: string;
readonly gender: 'Male' | 'Female';
}
let somchai: Person = {
fi
rstName: 'Somchai',
lastName: 'Haha',
gender: 'Male',
};
// Cannot assign to 'gender' because
// it is a read-only property.
somchai.gender = 'Female';
Babel Coder
TYPE ALIAS
interface Person {
name: string;
age: number;
gender: string;
}
type Person = {
name: string;
age: number;
gender: string;
};
interface Website {
url: string;
}
interface Article {
title: string;
content: string;
}
interface BlogPost extends Website, Article {
view: number;
}
type Website = {
url: string;
};
type Article = {
title: string;
content: string;
};
type BlogPost = Website &
Article & {
view: number;
};
Babel Coder
FUNCTION TYPES
function getFullName(
fi
rstName, lastName) {
return `${
fi
rstName} ${lastName}`;
}
function getFullName( fi
rstName: string, lastName: string): string {
return `${
fi
rstName} ${lastName}`;
}
const getFullName = function (
fi
rstName: string, lastName: string): string {
return `${
fi
rstName} ${lastName}`;
};
Babel Coder
FUNCTION TYPES
const getFullName = (
fi
rstName, lastName) => {
return `${
fi
rstName} ${lastName}`;
};
const getFullName = ( fi
rstName: string, lastName: string): string => {
return `${
fi
rstName} ${lastName}`;
};
type GetFullNameFn = (
fi
rstName: string, lastName: string) => string;
const getFullName: GetFullNameFn = (
fi
rstName, lastName) => {
return `${
fi
rstName} ${lastName}`;
};
Babel Coder
CONST ASSERTIONS
// const theme: {
// colors: {
// amethyst: "#9b59b6";
// carrot: string;
// };
// }
const theme = {
colors: {
amethyst: '#9b59b6' as const,
carrot: '#e67e22',
},
};
// const theme: {
// colors: {
// amethyst: string;
// carrot: string;
// };
// }
const theme = {
colors: {
amethyst: '#9b59b6',
carrot: '#e67e22',
},
};
// const theme: {
// readonly colors: {
// readonly amethyst: "#9b59b6";
// readonly carrot: "#e67e22";
// };
// }
const theme = {
colors: {
amethyst: '#9b59b6',
carrot: '#e67e22',
},
} as const;
Babel Coder
TYPEOF
const user = { name: 'Somchai' };
console.log(typeof user); // 'object'
// type User = {
// name: string;
// }
type User = typeof user;
Babel Coder
UNION TYPES
type Printable = string | string[];
const text: Printable = 'my message';
function format(thing: Printable): string {
if (Array.isArray(thing)) return thing.join(', ');
return thing;
}
Babel Coder
INTERSECTION TYPES
interface Identity {
id: number;
name: string;
}
interface Contact {
email: string;
phone: string;
address: string;
}
type Employee = Identity & Contact;
const somchai: Employee = {
id: 11001,
name: 'Somchai',
email: 'somchai@haha.com',
phone: '082-111-1111',
address: '111/11',
};
Babel Coder
CLASSES
class BankAccount {
static interestRate = 3.5;
balance: number;
constructor(balance: number) {
this.balance = balance;
}
getInterest() {
return this.balance * BankAccount.interestRate;
}
}
const myAcc1 = new BankAccount(20);
const myAcc2 = new BankAccount(30);
myAcc1.balance; // 20
myAcc1.getInterest(); // 70
myAcc1
balance: 20
getInterest
myAcc2
balance: 30
getInterest
getInterest
3.5
BankAccount
Babel Coder
ACCESS MODIFIERS
class BankAccount {
protected balance: number;
constructor(balance: number) {
this.balance = balance;
}
withdraw(amount: number) {
if (amount <= this.balance) this.balance -= amount;
}
deposit(amount: number) {
if (amount > 0) this.balance += amount;
}
}
class SavingAccount extends BankAccount {
static readonly interestRate = 3.5;
private readonly debitCard: number;
constructor(balance: number, debitCard: number) {
super(balance);
this.debitCard = debitCard;
}
getInterest() {
return this.balance * SavingAccount.interestRate;
}
}
Babel Coder
PARAMETER PROPERTIES
class BankAccount {
constructor(protected balance: number) {}
withdraw(amount: number) {
if (amount <= this.balance) this.balance -= amount;
}
deposit(amount: number) {
if (amount > 0) this.balance += amount;
}
}
class SavingAccount extends BankAccount {
static interestRate = 3.5;
constructor(
balance: number,
private readonly debitCard: number) {
super(balance);
}
getInterest() {
return this.balance * SavingAccount.interestRate;
}
}
Babel Coder
KEYWORD NEW
class Person {
constructor() {}
}
function get<T>(ctor: Factory<T>) {
return new ctor();
}
// const person: Person
const person = get(Person);
interface Factory<T> {
new (...args: any[]): T;
}
// OR
type Factory<T> = new (...args: any[]) => T;
Babel Coder
GENERIC FUNCTIONS
function lastNum(arr: number[], count: number) {
return arr.slice(arr.length - count);
}
lastNum([1, 2, 3, 4, 5], 3); // [3, 4, 5]
function lastStr(arr: string[], count: number) {
return arr.slice(arr.length - count);
}
lastStr(['A', 'B', 'C', 'D', 'E'], 2); // ['D', 'E']
function last<T>(arr: T[], count: number) {
return arr.slice(arr.length - count);
}
const last = <T>(arr: T[], count: number) => {
return arr.slice(arr.length - count);
};
last<string>(['A', 'B', 'C', 'D', 'E'], 2);
last(['A', 'B', 'C', 'D', 'E'], 2);
Babel Coder
GENERIC TYPES AND INTERFACES
const head = <T>(arr: T[]) => arr[0];
const tail = <T>(arr: T[]) => arr[arr.length - 1];
type GetItem<T> = (arr: T[]) => T;
interface GetItem<T> {
(arr: T[]): T;
}
const option: GetItem<number> = head;
option([1, 2, 3]);
function getItem<T>(list: T[], fn: GetItem<T>): T {
return fn(list);
}
getItem([1, 2, 3], head); // 1
getItem([1, 2, 3], tail); // 3
Babel Coder
UTILITY TYPES
Babel Coder
RECORD
type MyRecord<T extends string | number | symbol, U> = {
[K in T]: U;
};
type keys = 'name' | 'address';
// type MyPerson = {
// name: string;
// address: string;
// }
type MyPerson = MyRecord<keys, string>;
type Person = Record<keys, string>;
Babel Coder
PICK AND OMIT
type MyPick<T, K extends keyof T> = {
[P in K]: T[P];
};
type Person = {
name: string;
age: number;
address: string;
};
// type NameAndAge = {
// name: string;
// age: number;
// }
type MyNameAndAge = MyPick<Person, 'name' | 'age'>;
type NameAndAge = Pick<Person, 'name' | 'age'>;
type MyOmit<T, K extends string | number | symbol> = Pick<
T,
Exclude<keyof T, K>
>;
type Person = {
name: string;
age: number;
address: string;
};
// type MyAddress = {
// address: string;
// }
type MyAddress = MyOmit<Person, 'name' | 'age'>;
type Address = Omit<Person, 'name' | 'age'>;
Babel Coder
REQUIRED AND PARTIAL
type MyPartial<T> = {
[K in keyof T]?: T[K];
};
type Person = {
name: string;
age: number;
address: string;
};
// type MyPartialPerson = {
// name?: string | unde
fi
ned;
// age?: number | unde
fi
ned;
// address?: string | unde
fi
ned;
// }
type MyPartialPerson = MyPartial<Person>;
type PartialPerson = Partial<Person>;
type MyRequired<T> = {
[K in keyof T]-?: T[K];
};
type Person = {
name: string;
age: number;
address: string;
};
// type MyRequiredPerson = {
// name: string;
// age: number;
// address: string;
// }
type MyRequiredPerson = MyRequired<Person>;
type RequiredPerson = Required<Person>;
Babel Coder
READONLY
type MyReadonly<T> = {
readonly [K in keyof T]: T[K];
};
type Person = {
name: string;
age: number;
address: string;
};
// type MyReadOnlyPerson = {
// readonly name: string;
// readonly age: number;
// readonly address: string;
// }
type MyReadOnlyPerson = MyReadonly<Person>;
type ReadOnlyPerson = Readonly<Person>;
Babel Coder
DECLARATION FILES
Babel Coder
DEFINITELY TYPED
// Could not
fi
nd a declaration
fi
le for module 'lodash'.
import lodash from 'lodash';
yarn add @types/lodash
yarn add @types/absinthe__socket
Babel Coder
A JAVASCRIPT LIBRARY
FOR BUILDING USER INTERFACES
Declarative
Component-Based
Learn Once, Write Anywhere
Babel Coder
IMPERATIVE VS DECLARATIVE
HTML
<div id="counter">0</div>
<button id="incBtn">inc</button>
JavaScript
let count = 0
const incBtn = document.getElementById("incBtn")
const counter = document.getElementById("counter")
incBtn.onclick = function() {
counter.textContent = ++count
}
JSX
function Counter() {
const [count, setCount] = useState(0)
return (
<>
<div>{count}</div>
<button onClick={() => setCount(count + 1)}>inc</button>
</>
)
}
Imperative Declarative
Babel Coder
COMPONENT-BASED DESIGN
App
Jumbotron
Header PostList
PostItem
PostItem PostItem
Babel Coder
React React Native
React Native
for Windows + macOS
Babel Coder
COMPOSITION
App
function App() {
return (
<>
<SearchForm></SearchForm>
<SearchResults></SearchResults>
</>
)
}
function SearchForm() {
return <div>SearchForm</div>
}
function SearchResults() {
return <div>SearchResults</div>
}
SearchForm
SearchResults
Babel Coder
STATE
App
import React, { useState } from 'react'
function App() {
const [titles, setTitles] = useState(initialTitles)
return (
<>
<SearchForm></SearchForm>
<SearchResults></SearchResults>
</>
)
}
useState returns a pair: the current state value
and a function that lets you update it.
The only argument to useState is the initial state.
const initialTitles = [
'Reactive Programming
คื
ออะไร',
'เป
รี
ยบเ
ที
ยบ React, Vue และ Angular',
'Server Rendering'
]
Babel Coder
PROPS
App SearchResults
function App() {
const [titles, setTitles] = useState(initialTitles)
return (
<>
<SearchForm></SearchForm>
<SearchResults titles={titles}></SearchResults>
</>
)
}
function SearchResults(props) {
return <div>{props.titles[0]}</div>
}
App
SearchForm SearchResults
titles
titles
props
Babel Coder
DATA TRANSFORMATION
SearchResults
function SearchResults(props) {
return (
<ul>
{props.titles.map((title, index) => (
<li key={index}>{title}</li>
))}
</ul>
)
}
Reactive Programming
คื
ออะไร
เป
รี
ยบเ
ที
ยบ React, Vue และ Angular
Server Rendering
Reactive Programming
คื
ออะไร
เป
รี
ยบเ
ที
ยบ React Vue และ Angular
Server Rendering
li tag
Babel Coder
EVENT HANDLER
App
function SearchForm() {
const [input, setInput] = useState('')
const onInputChange = event => setInput(event.target.value)
return (
<input
type="text"
value={input}
onChange={onInputChange}
/>
)
}
state
[input setInput]
Input Tag
value onChange
event.target.value
Babel Coder
EVENTS
Touch & Mouse
Keyboard
Other
Babel Coder
PARENT-CHILD COMMUNICATION
App
function App() {
const [titles, setTitles] = useState(initialTitles)
const search = keyword => {
const result =
keyword === ''
? initialTitles
: titles.
fi
lter(title => title.includes(keyword))
setTitles(result)
}
return (
<>
<SearchForm onSubmit={search}></SearchForm>
<SearchResults titles={titles}></SearchResults>
</>
)
} SearchForm
function SearchForm(props) {
const [input, setInput] = useState('')
const onInputChange = event => {
const input = event.target.value
setInput(input)
props.onSubmit(input)
}
return (
<input type="text"
value={input}
onChange={onInputChange} />
}
Babel Coder
PARENT-CHILD COMMUNICATION
Reactive Programming
คื
ออะไร
เป
รี
ยบเ
ที
ยบ React Vue และ Angular
Server Rendering
App
SearchForm SearchResults
titles
onChange
action
up
data
down
Babel Coder
COMPONENT LIFECYCLE
Component
state
render
Hello World
Mounting
Mounted Hello Thailand
Updating
Unmounting
Updated Unmounted
props
Babel Coder
REACT HOOKS
Hooks are functions that let you “hook into” React state and lifecycle features from function
components.
RULES OF HOOKS
• Only call Hooks at the top level. Don’t call Hooks inside loops, conditions, or nested functions.
• Only call Hooks from React function components. Don’t call Hooks from regular JavaScript functions
(except custom hooks).
Babel Coder
STATE MANAGEMENT
import React, { useState } from 'react'
function App() {
const [count, setCount] = useState(0)
return (
<button
onClick={() => setCount(count + 1)}>
{count}
</button>
)
}
0
count
onClick
setCount
Babel Coder
LIFECYCLE MANAGEMENT
function App() {
const [count, setCount] = useState(0)
useE
ff
ect(() => {
const timer = setInterval(() => setCount(count + 1), 1000)
return () => clearInterval(timer)
}, [count])
return <div>{count}</div>
}
Call after mounted and updated
Call before unmounted
Babel Coder
EXAMPLE 1
App
function App() {
const [msg, setMsg] = useState('')
return (
<>
<input
type="text"
value={msg}
onChange={event => setMsg(event.target.value)}
/>
<Counter msg={msg}></Counter>
</>
)
}
Counter
function Counter({ msg }) {
const [count, setCount] = useState(0)
useE
ff
ect(() => {
const timer = setInterval(() => setCount(count + 1), 1000)
document.title = `${msg} ${count}`
return () => clearInterval(timer)
}, [count, msg])
return <div>{count}</div>
}
Babel Coder
MANAGE MUTABLE REF OBJECT
useRef returns a mutable ref object whose .current property is initialized to the passed argument
(initialValue). The returned object will persist for the full lifetime of the component.
WHEN TO USE REF
• Managing focus, text selection, or media playback.
• Integrating with third-party DOM libraries.
• Triggering imperative animations.
Babel Coder
REF TO ELEMENT
function App() {
const inputEl = useRef(null)
return (
<>
<input type="text" ref={inputEl} />
<button onClick={() => inputEl.current.focus()}>Focus</button>
</>
)
}
Babel Coder
MUTABLE OBJECT
function App() {
const counter = useRef(0)
const increase = () => {
counter.current += 1
console.log(counter.current)
}
return (
<>
<div>{counter.current}</div>
<button onClick={increase}>Focus</button>
</>
)
}
Changed
Unchanged
• A ref created with useRef will be created only when
the component has been mounted and preserved
during the full lifecycle.
• Refs can be used for accessing DOM nodes or React
elements, and for keeping mutable variables (like
instance variables in class components).
• Updating a ref is a side effect so it should be done
only inside an useEffect (or useLayoutEffect) or
inside an event handler.
Babel Coder
CUSTOM HOOKS
function useInterval(initialCount) {
const [count, setCount] = useState(initialCount)
useE
ff
ect(() => {
const timer = setInterval(() => setCount(count + 1), 1000)
return () => clearInterval(timer)
})
return count
}
function App() {
const count = useInterval(0)
return <div>{count}</div>
}
Babel Coder
HOOKS AND LIFECYCLE
Mounting Updating Unmounting
render
React updates DOM and ref
Layout Cleanup
Layout Effect
Effect Cleanup
Effect
Render Phase
Pure, no side e
ff
ect. May be paused,
aborted or restarted by React.
Reconciliation Phase
Handled by React
Layout Phase
Can work with DOM,
but blocks the rendering
Commit Phase
Can work with DOM,
run side e
ff
ects, schedule updates
Babel Coder
CONTEXT
const themes = {
light: {
foreground: '#000000',
background: '#eeeeee'
},
dark: {
foreground: '#
ff
ff
ff
',
background: '#222222'
}
}
function App() {
const [theme, setTheme] = useState(themes.light)
return <AddressBook theme={theme}></AddressBook>
}
function AddressBook({ theme }) {
return <AddressList theme={theme}></AddressList>
}
function AddressList({ theme }) {
return <div style={{ background: theme.background }}></div>
}
Babel Coder
CONTEXT
App
Address
Book
Address
List
theme
provide
consume
theme
<ThemeContext.Provider value={theme}>
</ThemeContext.Provider>
<ThemeContext.Consumer>
</ThemeContext.Consumer>
Babel Coder
CONTEXT
import { createContext } from 'react'
export const themes = {
light: {
foreground: '#000000',
background: '#eeeeee'
},
dark: {
foreground: '#
ff
ff
ff
',
background: '#222222'
}
}
export default createContext(themes.light)
lib/theme.js
Babel Coder
CONTEXT
import ThemeContext, { themes } from './lib/theme'
import AddressBook from './AddressBook'
export default function App() {
const [theme, setTheme] = useState(themes.light)
const switchTheme = () => {
setTheme(theme === themes.light ? themes.dark : themes.light)
}
return (
<ThemeContext.Provider value={theme}>
<button onClick={switchTheme}>Switch Theme</button>
<AddressBook></AddressBook>
</ThemeContext.Provider>
)
}
function AddressList({ addresses }) {
return (
<ThemeContext.Consumer>
{theme => (
<ul style={{ background: theme.background, color: theme.foreground }}>
{addresses.map(({ id, address }) => (
<li key={id}>{address}</li>
))}
</ul>
)}
</ThemeContext.Consumer>
)
}
App AddressList
Babel Coder
CONTEXT
AddressList
function AddressList({ addresses }) {
const theme = useContext(ThemeContext)
return (
<ul style={{ background: theme.background, color: theme.foreground }}>
{addresses.map(({ id, address }) => (
<li key={id}>{address}</li>
))}
</ul>
)
}
Babel Coder
TAILWIND CSS
Babel Coder
EXPRESS
import express from 'express'
const app = express()
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(3000, () =>
console.log(`App listening on http://0.0.0.0:3000`)
)
Babel Coder
RESTFUL API
Babel Coder
RESTFUL
• Stands for “Representational State Transfer”
• RESTful Web Services are one way of providing interoperability between computer systems on
the Internet.
Babel Coder
TRADITIONAL WEB ARCHITECTURES
Server
Presentation
Application
Persistence
Browser
Babel Coder
CLIENT SERVER
Internet
Client Server
Babel Coder
RESOURCES
Internet
Client Server
User
Article
Comment
Babel Coder
UNIFORM INTERFACE
User
Article
Comment
URL
/users/1
GET
POST
PUT
PATCH
DELETE
HTTP VERBS
Babel Coder
ACTIONS
User
Article
Comment
URL
/users
GET
POST
PUT
PATCH
DELETE
List All Users
Create New User
Babel Coder
ACTIONS
User
Article
Comment
URL
/users/1
GET
POST
PUT
PATCH
DELETE
List the User
Partial Update the User
Delete the User
Babel Coder
MIME-TYPES
User
Article
Comment
URL
/users/1
HTML
XML
JSON
text/html
application/xml
application/json
Babel Coder
STATELESS
Internet
Client Server
User
Article
Comment
Babel Coder
HTTP STATUS CODES
CODE STATUS
1xx Informational responses
2xx Success
3xx Redirection
4xx Client Errors
5xx Server Errors
Babel Coder
HTTP STATUS CODES
CODE STATUS
200 OK
201 Created
204 No Content
401 Unauthorized
404 Not Found
405 Method Not Allowed
422 Unprocessable Entity
500 Internal Server Error
Babel Coder
MODEL-VIEW-CONTROLLER
Controller
View
Model
Request
UI Logic
Business Logic
DB
Response
Babel Coder
MODEL-VIEW-CONTROLLER
Controller
View
Model
Request UI Logic
Business Logic
Manipulate
DB
Dispatch
Router
Babel Coder
EXPRESS.JS
Babel Coder
EXPRESS
import express from 'express'
const app = express()
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(3000, () =>
console.log(`App listening on http://0.0.0.0:3000`)
)
Babel Coder
MIDDLEWARE
app = express()
app.use(function (req, res, next) {
console.log('Time:', Date.now())
next()
})
app.use(function (err, req, res, next) {
console.error(err.stack)
res.status(500).send('Something broke!')
})
Babel Coder
ROUTE-LEVEL MIDDLEWARE
const app = express()
const router = express.Router()
router.get(
'/', (req, res) => res.send('Articles')
)
router.post(
'/', (req, res) => res.send(req.body.title)
)
app.use('/articles', router)
GET /articles
POST /articles
import bodyParser from 'body-parser'
app.use(bodyParser.json())
Babel Coder
NAMED PARAMETERS
app = express()
app.get(
'/articles/:id', (req, res) => res.send(req.params.id)
)
Babel Coder
BODY VALIDATOR
const bodyValidator =
<T extends Type<object>>(Dto: T): RequestHandler =>
async (req, _res, next) => {
const dto = plainToInstance(Dto, req.body, { strategy: 'excludeAll' });
const errors = await validate(dto);
if (errors.length > 0) return next(new ValidationError(errors));
req.body = dto;
next();
};
export const register: RequestHandler[] = [
bodyValidator(SignUpFormDto),
authenticator.signUp,
async (req, res) => {
res.status(HTTP_STATUSES.CREATED).json(new UserResponseDto(req.user));
},
];
export class SignUpFormDto {
@Expose()
@IsEmail()
email: string;
@Expose()
@Length(8)
password: string;
@Expose()
name: string;
}
import { ValidationError as Err } from 'class-validator';
export class ValidationError extends Error {
constructor(public errors: Err[]) {
super('Validation Error');
}
}
Babel Coder
RESPONSE TRANSFORMER
const responseTransformer: RequestHandler = (_req, res, next) => {
const oldJson = res.json;
res.json = (body) => {
if ('errors' in body) return oldJson.call(res, body);
return oldJson.call(
res,
instanceToPlain(body, {
strategy: 'excludeAll',
})
);
};
next();
};
export class UserResponseDto {
@Expose()
name: string;
@Expose()
email: string;
@Expose()
avatar: string;
@Expose()
role: Role;
constructor(user: User) {
Object.assign(this, user);
}
}
Babel Coder
ERROR HANDLER
const errorHandler: ErrorRequestHandler = (err, _req, res, next) => {
if (err instanceof ValidationError) {
res.status(HTTP_STATUSES.BAD_REQUEST).json({ errors: err.errors });
}
if (err instanceof QueryFailedError) {
res.status(HTTP_STATUSES.BAD_REQUEST).json({ errors: err.message });
}
next(err);
};
Babel Coder
TYPEORM
export const AppDataSource = new DataSource({
type: 'mssql',
host: con
fi
g.database.host,
port: con
fi
g.database.port,
username: con
fi
g.database.username,
password: con
fi
g.database.password,
database: con
fi
g.database.name,
synchronize: false,
logging: true,
subscribers: [],
entities: [User],
migrations,
extra: {
trustServerCerti
fi
cate: true,
trustedConnection: true,
},
options: {
useUTC: true,
encrypt: true,
},
});
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ unique: true })
name: string;
@Column({ unique: true })
email: string;
@Column()
password: string;
@Column({
type: 'int',
default: Role.MEMBER,
})
role: Role;
@Column({ nullable: true })
avatar?: string;
@Column({ nullable: true, unique: true })
refreshToken?: string;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
updatedAt: Date;
@BeforeInsert()
async hashPassword() {
const hash = await bcrypt.hash(this.password, 10);
this.password = hash;
}
isValidPassword(password: string) {
return bcrypt.compare(password, this.password);
}
}
const migrations = [
CreateUserTable1677496221672,
];
export default migrations;
Babel Coder
MIGRATION
project.json
{
"targets": {
"migration:create": {
"executor": "nx:run-commands",
"options": {
"envFile": "apps/api/.env",
"command": "npm run typeorm migration:create -- apps/api/src/data/migration/{args.name} -- -d apps/api/src/data/data-source.ts"
}
},
"migration:generate": {
"executor": "nx:run-commands",
"options": {
"envFile": "apps/api/.env",
"command": "npm run typeorm migration:generate -- -d apps/api/src/data/data-source.ts apps/api/src/data/migration/{args.name}"
}
},
"migration:run": {
"executor": "nx:run-commands",
"options": {
"envFile": "apps/api/.env",
"command": "npm run typeorm migration:run -- -d apps/api/src/data/data-source.ts"
}
},
"migration:revert": {
"executor": "nx:run-commands",
"options": {
"envFile": "apps/api/.env",
"command": "npm run typeorm migration:revert -- -d apps/api/src/data/data-source.ts"
}
},
},
"tags": []
}
nx run api:migration:generate --name CreateUserTable
nx run api:migration:run
nx run api:migration:revert
nx run api:migration:create --name AddRefreshTokenToUserTable
Babel Coder
AUTHENTICATION /
AUTHORIZATION
Babel Coder
AUTHENTICATION & AUTHORIZATION
Authentication
Articles
Authorization
Authentication is the process of ascertaining that somebody really is who he claims
to be.
Authorization refers to rules that determine who is allowed to do what.
Babel Coder
SESSIONS
A
B
C
423432g2f3j23
g23hg42j4h2k3
jh3g56jh5gj333
423432g2f3j23
g23hg42j4h2k3
jh3g56jh5gj333
423432g2f3j23
g23hg42j4h2k3
jh3g56jh5gj333
stateful token stateless token
Babel Coder
JSON WEB TOKEN
<HEADER>.<PAYLOAD>.<SIGNATURE>
JSON Web Token (JWT) is a JSON-based open standard (RFC 7519) for
creating access tokens that assert some number of claims.
Header
{
"alg": "HS256",
"typ": "JWT"
}
base64UrlEncode eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Payload
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
base64UrlEncode
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI
6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
Signature
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
Babel Coder
PAYLOAD
Subject
sub This holds the identifier for the token
Issued At
iat When the token was issued (unix timestamp)
Expiry
exp The token expiry date (unix timestamp)
Issuer
iss The issuer of the token
Babel Coder
AUTH ROUTING
router.route('/auth');
router.post('/auth/sign-up', authController.register);
router.post('/auth/sign-in', authController.login);
router.get('/auth/pro
fi
le', authController.getPro
fi
le);
router.patch('/auth/pro
fi
le', authController.updatePro
fi
le);
router.post('/auth/refresh-token', authController.refreshToken);
router.delete('/auth/sign-out', authController.signOut);
Babel Coder
MIDDLEWARE
import { RequestHandler } from 'express';
import passport from 'passport';
import { compose } from 'compose-middleware';
export const signUp = passport.authenticate('sign-up', { session: false });
export const signIn = passport.authenticate('sign-in', { session: false });
export const accessToken: RequestHandler = compose([
passport.initialize({ userProperty: 'userFromToken' }),
passport.authenticate('access-token', {
session: false,
}),
]);
export const refreshToken = passport.authenticate('refresh-token', {
session: false,
});
import { RequestHandler } from 'express';
import { Role } from '../entity/User';
import { HTTP_STATUSES } from '../helper/http-statuses';
import { accessToken } from './authenticator';
export const permitFor = (roles: Role | Role[]) => [
accessToken,
authorizer(roles),
];
const authorizer =
(roles: Role | Role[]): RequestHandler =>
(req, res, next) => {
const role = req.userFromToken.role;
if (Array.isArray(roles) && roles.includes(role)) return next();
if (roles === role) return next();
res.sendStatus(HTTP_STATUSES.FORBIDDEN);
};
export default authorizer;
Authenticator Authorizer
Babel Coder
CONTROLLER
const upload = multer({ dest: path.join(__dirname, 'uploads', 'users') });
export const register: RequestHandler[] = [
bodyValidator(SignUpFormDto),
authenticator.signUp,
async (req, res) => {
res.status(HTTP_STATUSES.CREATED).json(new UserResponseDto(req.user));
},
];
export const login: RequestHandler[] = [
authenticator.signIn,
async (req, res, next) => {
const user = req.user;
req.login(user, { session: false }, async (error) => {
if (error) return next(error);
const { accessToken, refreshToken } = authService.signAndSaveTokens(user);
return res
.status(HTTP_STATUSES.CREATED)
.json(new LoginResponseDto(accessToken, refreshToken, user));
});
},
];
export const getPro
fi
le: RequestHandler[] = [
authenticator.accessToken,
async (req, res) => {
const user = await userService.getUserById(req.userFromToken.id);
res.json(new UserResponseDto(user));
},
];
export const updatePro
fi
le: RequestHandler[] = [
upload.single('avatar'),
authenticator.accessToken,
bodyValidator(UpdatePro
fi
leFormDto),
async (req, res) => {
const payload: UpdatePro
fi
leFormDto & { avatar: string } = req.body;
if (req.
fi
le) payload.avatar = `uploads/users/${req.
fi
le.
fi
lename}`;
const user = await userService.updateUser(req.userFromToken.id, payload);
res.json(new UserResponseDto(user));
},
];
export const refreshToken: RequestHandler[] = [
bodyValidator(RefreshTokenFormDto),
authenticator.refreshToken,
async (req, res) => {
const user = req.user;
const { accessToken, refreshToken } = authService.signAndSaveTokens(user);
return res
.status(HTTP_STATUSES.CREATED)
.json(new LoginResponseDto(accessToken, refreshToken, user));
},
];
export const signOut: RequestHandler[] = [
authenticator.accessToken,
async (req, res) => {
const user = req.user;
await authService.signOut(user);
res.json(new LoginResponseDto(null, null, user));
},
];
Babel Coder
SERVICE
const userRepository = AppDataSource.getRepository(User);
export const signAndSaveTokens = (user: User) => {
const accessToken = jwt.sign(
{ sub: user.id, role: user.role },
con
fi
g.secretKey.accessToken,
{ expiresIn: con
fi
g.expiresIn.accessToken }
);
const refreshToken = jwt.sign(
{ sub: user.id },
con
fi
g.secretKey.accessToken,
{ expiresIn: con
fi
g.expiresIn.refreshToken }
);
user.refreshToken = refreshToken;
userRepository.save(user);
return { accessToken, refreshToken };
};
export const signOut = async (user: User) => {
user.refreshToken = null;
await userRepository.save(user);
};
const userRepository = AppDataSource.getRepository(User);
export const getUserById = (id: number) => {
return userRepository.
fi
ndOneBy({ id });
};
export const updateUser = async (id: number, form: Partial<User>) => {
const currentUser = await getUserById(id);
const currentAvatar = currentUser.avatar;
const user = userRepository.create(form);
if (user.password) await user.hashPassword();
await userRepository.update(id, user);
if (user.avatar) {
fs.rm(path.join(__dirname, currentAvatar), { force: true });
}
return getUserById(id);
};
auth user
Babel Coder
TESTING
Babel Coder
Delightful JavaScript Testing
yarn test
Babel Coder
TESTING PYRAMID
Unit Tests
Integration Tests
UI Tests
ensure that modules which work well in isolation,
also play well together.
Unit testing
• focus on testing small units
• tested in isolation and independent of other units.
• Unit tests should be fast.
End-to-end testing is a methodology used to test whether
the
fl
ow of an application is performing
as designed from start to
fi
nish.
Babel Coder
The Testing Pyramid
Babel Coder
The Testing Trophy
https://twitter.com/kentcdodds/status/960723172591992832/photo/1
TypeScript / ESLint
Cypress
Babel Coder
Babel Coder
API
UI
Babel Coder
API
1
2
3
E2E Testing
Babel Coder
Mock Data
1
2
3
Integration Testing
Babel Coder
SearchBox
ArticleList
Babel Coder
<SearchBox
placeholder={placeholder}
onSearch={onSearch}
/>
Unit Testing / Component Testing
render(
)
Babel Coder
Unit Testing / Component Testing
<ArticleList keyword={keyword} />
render(
)
Babel Coder
TEST CASES
function multiply(a, b) {
return a * b
}
multiply.js
describe(‘multiply', () => {
it('multiplies two numbers correctly', () => {
expect(multiply(3, 2)).toBe(6)
})
})
multiply.test.js
Matchers
Babel Coder
TRUTHINESS
it('null', () => {
const n = null
expect(n).toBeNull()
expect(n).toBeDe
fi
ned()
expect(n).not.toBeUnde
fi
ned()
expect(n).not.toBeTruthy()
expect(n).toBeFalsy()
})
it('zero', () => {
const z = 0
expect(z).not.toBeNull()
expect(z).toBeDe
fi
ned()
expect(z).not.toBeUnde
fi
ned()
expect(z).not.toBeTruthy()
expect(z).toBeFalsy()
})
Babel Coder
NUMBERS
it('two plus two', () => {
const value = 2 + 2
expect(value).toBeGreaterThan(3)
expect(value).toBeGreaterThanOrEqual(3.5)
expect(value).toBeLessThan(5)
expect(value).toBeLessThanOrEqual(4.5)
// toBe and toEqual are equivalent for numbers
expect(value).toBe(4)
expect(value).toEqual(4)
})
it('adding
fl
oating point numbers', () => {
const value = 0.1 + 0.2
//expect(value).toBe(0.3) This won't work because of rounding error
expect(value).toBeCloseTo(0.3)
})
Babel Coder
STRINGS
it('there is no I in team', () => {
expect('team').not.toMatch(/I/)
})
it('but there is a "stop" in Christoph', () => {
expect('Christoph').toMatch(/stop/)
})
Babel Coder
ARRAYS
const programmingLangs = [
'JavaScript',
'Python',
'C/C++',
'Java',
'R'
]
it('the programming list has R on it', () => {
expect(programmingLangs).toContain('R')
})
Babel Coder
EXCEPTIONS
function compileAndroidCode() {
throw new Con
fi
gError('you are using the wrong JDK')
}
it('compiling android goes as expected', () => {
expect(compileAndroidCode).toThrow()
expect(compileAndroidCode).toThrow(Con
fi
gError)
// You can also use the exact error message or a regexp
expect(compileAndroidCode).toThrow('you are using the wrong JDK')
expect(compileAndroidCode).toThrow(/JDK/)
})
Babel Coder
MOCK FUNCTIONS
function sum(nums, cb) {
const result = nums.reduce((result, num) => result + num)
cb(result)
}
describe('sum', () => {
it('calls callback correctly', () => {
const fn = jest.fn()
sum([1, 2, 3], fn)
expect(fn.mock.calls.length).toBe(1)
expect(fn.mock.calls[0][0]).toBe(6)
})
})
Babel Coder
SETUP AND TEARDOWN
beforeAll(() => console.log('1 - beforeAll'))
afterAll(() => console.log('1 - afterAll'))
beforeEach(() => console.log('1 - beforeEach'))
afterEach(() => console.log('1 - afterEach'))
it('', () => console.log('1 - test'))
describe('Scoped / Nested block', () => {
beforeAll(() => console.log('2 - beforeAll'))
afterAll(() => console.log('2 - afterAll'))
beforeEach(() => console.log('2 - beforeEach'))
afterEach(() => console.log('2 - afterEach'))
it('', () => console.log('2 - test'))
})
// 1 - beforeAll
// 1 - beforeEach
// 1 - test
// 1 - afterEach
// 2 - beforeAll
// 1 - beforeEach
// 2 - beforeEach
// 2 - test
// 2 - afterEach
// 1 - afterEach
// 2 - afterAll
// 1 - afterAll

More Related Content

Similar to Babel Coder JavaScript recap template literals fetch axios

JavaScript - Agora nervoso
JavaScript - Agora nervosoJavaScript - Agora nervoso
JavaScript - Agora nervosoLuis Vendrame
 
Mongoskin - Guilin
Mongoskin - GuilinMongoskin - Guilin
Mongoskin - GuilinJackson Tian
 
React Development with the MERN Stack
React Development with the MERN StackReact Development with the MERN Stack
React Development with the MERN StackTroy Miles
 
javascript for modern application.pdf
javascript for modern application.pdfjavascript for modern application.pdf
javascript for modern application.pdfNuttavutThongjor1
 
React Native One Day
React Native One DayReact Native One Day
React Native One DayTroy Miles
 
Javascript the New Parts v2
Javascript the New Parts v2Javascript the New Parts v2
Javascript the New Parts v2Federico Galassi
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016Manoj Kumar
 
JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6Solution4Future
 
ECMAScript2015
ECMAScript2015ECMAScript2015
ECMAScript2015qmmr
 
Introduction to ECMAScript 2015
Introduction to ECMAScript 2015Introduction to ECMAScript 2015
Introduction to ECMAScript 2015Tomasz Dziuda
 
JavaScript Objects and OOP Programming with JavaScript
JavaScript Objects and OOP Programming with JavaScriptJavaScript Objects and OOP Programming with JavaScript
JavaScript Objects and OOP Programming with JavaScriptLaurence Svekis ✔
 
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6Dmitry Soshnikov
 

Similar to Babel Coder JavaScript recap template literals fetch axios (20)

cypress.pdf
cypress.pdfcypress.pdf
cypress.pdf
 
Introduction to Groovy
Introduction to GroovyIntroduction to Groovy
Introduction to Groovy
 
JavaScript - Agora nervoso
JavaScript - Agora nervosoJavaScript - Agora nervoso
JavaScript - Agora nervoso
 
ECMAScript 6
ECMAScript 6ECMAScript 6
ECMAScript 6
 
Intro to Ember.JS 2016
Intro to Ember.JS 2016Intro to Ember.JS 2016
Intro to Ember.JS 2016
 
Mongoskin - Guilin
Mongoskin - GuilinMongoskin - Guilin
Mongoskin - Guilin
 
React Development with the MERN Stack
React Development with the MERN StackReact Development with the MERN Stack
React Development with the MERN Stack
 
javascript for modern application.pdf
javascript for modern application.pdfjavascript for modern application.pdf
javascript for modern application.pdf
 
React Native One Day
React Native One DayReact Native One Day
React Native One Day
 
Javascript the New Parts v2
Javascript the New Parts v2Javascript the New Parts v2
Javascript the New Parts v2
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016
 
ES6 Overview
ES6 OverviewES6 Overview
ES6 Overview
 
JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6
 
ECMAScript2015
ECMAScript2015ECMAScript2015
ECMAScript2015
 
Js hacks
Js hacksJs hacks
Js hacks
 
Introduction to ECMAScript 2015
Introduction to ECMAScript 2015Introduction to ECMAScript 2015
Introduction to ECMAScript 2015
 
JavaScript Objects and OOP Programming with JavaScript
JavaScript Objects and OOP Programming with JavaScriptJavaScript Objects and OOP Programming with JavaScript
JavaScript Objects and OOP Programming with JavaScript
 
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
 
ES6 is Nigh
ES6 is NighES6 is Nigh
ES6 is Nigh
 
Latinoware
LatinowareLatinoware
Latinoware
 

More from NuttavutThongjor1

Intro to Modern DevOps.pdfIntro to Modern DevOps.pdfIntro to Modern DevOps.pdf
Intro to Modern DevOps.pdfIntro to Modern DevOps.pdfIntro to Modern DevOps.pdfIntro to Modern DevOps.pdfIntro to Modern DevOps.pdfIntro to Modern DevOps.pdf
Intro to Modern DevOps.pdfIntro to Modern DevOps.pdfIntro to Modern DevOps.pdfNuttavutThongjor1
 
10 วัฒนธรรมองค์กรของ DevOps.pdf10 วัฒนธรรมองค์กรของ DevOps.pdf
10 วัฒนธรรมองค์กรของ DevOps.pdf10 วัฒนธรรมองค์กรของ DevOps.pdf10 วัฒนธรรมองค์กรของ DevOps.pdf10 วัฒนธรรมองค์กรของ DevOps.pdf
10 วัฒนธรรมองค์กรของ DevOps.pdf10 วัฒนธรรมองค์กรของ DevOps.pdfNuttavutThongjor1
 
9 logging and monitoring.pdf 9 logging and monitoring.pdf
9 logging and monitoring.pdf 9 logging and monitoring.pdf9 logging and monitoring.pdf 9 logging and monitoring.pdf
9 logging and monitoring.pdf 9 logging and monitoring.pdfNuttavutThongjor1
 
8 iac.pdf 8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf
8 iac.pdf 8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf 8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf
8 iac.pdf 8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdfNuttavutThongjor1
 
7 cicd.pdf 7 cicd.pdf 7 cicd.pdf 7 cicd.pdf
7 cicd.pdf 7 cicd.pdf 7 cicd.pdf 7 cicd.pdf7 cicd.pdf 7 cicd.pdf 7 cicd.pdf 7 cicd.pdf
7 cicd.pdf 7 cicd.pdf 7 cicd.pdf 7 cicd.pdfNuttavutThongjor1
 
6 GitOps คืออะไร.pdf 6 GitOps คืออะไร.pdf 6 GitOps คืออะไร.pdf
6 GitOps คืออะไร.pdf 6 GitOps คืออะไร.pdf 6 GitOps คืออะไร.pdf6 GitOps คืออะไร.pdf 6 GitOps คืออะไร.pdf 6 GitOps คืออะไร.pdf
6 GitOps คืออะไร.pdf 6 GitOps คืออะไร.pdf 6 GitOps คืออะไร.pdfNuttavutThongjor1
 
5 Kubernetes.pdf 5 Kubernetes.pdf 5 Kubernetes.pdf
5 Kubernetes.pdf 5 Kubernetes.pdf 5 Kubernetes.pdf5 Kubernetes.pdf 5 Kubernetes.pdf 5 Kubernetes.pdf
5 Kubernetes.pdf 5 Kubernetes.pdf 5 Kubernetes.pdfNuttavutThongjor1
 
4 Docker.pdf 4 Docker.pdf 4 Docker.pdf 4 Docker.pdf
4 Docker.pdf 4 Docker.pdf 4 Docker.pdf 4 Docker.pdf4 Docker.pdf 4 Docker.pdf 4 Docker.pdf 4 Docker.pdf
4 Docker.pdf 4 Docker.pdf 4 Docker.pdf 4 Docker.pdfNuttavutThongjor1
 
3 Microservices.pdf 3 Microservices 3 Microservices.pdf.pdf
3 Microservices.pdf 3 Microservices 3 Microservices.pdf.pdf3 Microservices.pdf 3 Microservices 3 Microservices.pdf.pdf
3 Microservices.pdf 3 Microservices 3 Microservices.pdf.pdfNuttavutThongjor1
 
2 เทคโนโลยี cloud computing.pdf 2 เทคโนโลยี cloud computing.pdf
2 เทคโนโลยี cloud computing.pdf 2 เทคโนโลยี cloud computing.pdf2 เทคโนโลยี cloud computing.pdf 2 เทคโนโลยี cloud computing.pdf
2 เทคโนโลยี cloud computing.pdf 2 เทคโนโลยี cloud computing.pdfNuttavutThongjor1
 
1 devops คืออะไร.pdf 1 devops คืออะไร.pdf
1 devops คืออะไร.pdf 1 devops คืออะไร.pdf1 devops คืออะไร.pdf 1 devops คืออะไร.pdf
1 devops คืออะไร.pdf 1 devops คืออะไร.pdfNuttavutThongjor1
 
angular fundamentals.pdf angular fundamentals.pdf
angular fundamentals.pdf angular fundamentals.pdfangular fundamentals.pdf angular fundamentals.pdf
angular fundamentals.pdf angular fundamentals.pdfNuttavutThongjor1
 
mean stack mean stack mean stack mean stack
mean stack mean stack  mean stack  mean stackmean stack mean stack  mean stack  mean stack
mean stack mean stack mean stack mean stackNuttavutThongjor1
 

More from NuttavutThongjor1 (20)

Intro to Modern DevOps.pdfIntro to Modern DevOps.pdfIntro to Modern DevOps.pdf
Intro to Modern DevOps.pdfIntro to Modern DevOps.pdfIntro to Modern DevOps.pdfIntro to Modern DevOps.pdfIntro to Modern DevOps.pdfIntro to Modern DevOps.pdf
Intro to Modern DevOps.pdfIntro to Modern DevOps.pdfIntro to Modern DevOps.pdf
 
10 วัฒนธรรมองค์กรของ DevOps.pdf10 วัฒนธรรมองค์กรของ DevOps.pdf
10 วัฒนธรรมองค์กรของ DevOps.pdf10 วัฒนธรรมองค์กรของ DevOps.pdf10 วัฒนธรรมองค์กรของ DevOps.pdf10 วัฒนธรรมองค์กรของ DevOps.pdf
10 วัฒนธรรมองค์กรของ DevOps.pdf10 วัฒนธรรมองค์กรของ DevOps.pdf
 
9 logging and monitoring.pdf 9 logging and monitoring.pdf
9 logging and monitoring.pdf 9 logging and monitoring.pdf9 logging and monitoring.pdf 9 logging and monitoring.pdf
9 logging and monitoring.pdf 9 logging and monitoring.pdf
 
8 iac.pdf 8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf
8 iac.pdf 8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf 8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf
8 iac.pdf 8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf8 iac.pdf
 
7 cicd.pdf 7 cicd.pdf 7 cicd.pdf 7 cicd.pdf
7 cicd.pdf 7 cicd.pdf 7 cicd.pdf 7 cicd.pdf7 cicd.pdf 7 cicd.pdf 7 cicd.pdf 7 cicd.pdf
7 cicd.pdf 7 cicd.pdf 7 cicd.pdf 7 cicd.pdf
 
6 GitOps คืออะไร.pdf 6 GitOps คืออะไร.pdf 6 GitOps คืออะไร.pdf
6 GitOps คืออะไร.pdf 6 GitOps คืออะไร.pdf 6 GitOps คืออะไร.pdf6 GitOps คืออะไร.pdf 6 GitOps คืออะไร.pdf 6 GitOps คืออะไร.pdf
6 GitOps คืออะไร.pdf 6 GitOps คืออะไร.pdf 6 GitOps คืออะไร.pdf
 
5 Kubernetes.pdf 5 Kubernetes.pdf 5 Kubernetes.pdf
5 Kubernetes.pdf 5 Kubernetes.pdf 5 Kubernetes.pdf5 Kubernetes.pdf 5 Kubernetes.pdf 5 Kubernetes.pdf
5 Kubernetes.pdf 5 Kubernetes.pdf 5 Kubernetes.pdf
 
4 Docker.pdf 4 Docker.pdf 4 Docker.pdf 4 Docker.pdf
4 Docker.pdf 4 Docker.pdf 4 Docker.pdf 4 Docker.pdf4 Docker.pdf 4 Docker.pdf 4 Docker.pdf 4 Docker.pdf
4 Docker.pdf 4 Docker.pdf 4 Docker.pdf 4 Docker.pdf
 
3 Microservices.pdf 3 Microservices 3 Microservices.pdf.pdf
3 Microservices.pdf 3 Microservices 3 Microservices.pdf.pdf3 Microservices.pdf 3 Microservices 3 Microservices.pdf.pdf
3 Microservices.pdf 3 Microservices 3 Microservices.pdf.pdf
 
2 เทคโนโลยี cloud computing.pdf 2 เทคโนโลยี cloud computing.pdf
2 เทคโนโลยี cloud computing.pdf 2 เทคโนโลยี cloud computing.pdf2 เทคโนโลยี cloud computing.pdf 2 เทคโนโลยี cloud computing.pdf
2 เทคโนโลยี cloud computing.pdf 2 เทคโนโลยี cloud computing.pdf
 
1 devops คืออะไร.pdf 1 devops คืออะไร.pdf
1 devops คืออะไร.pdf 1 devops คืออะไร.pdf1 devops คืออะไร.pdf 1 devops คืออะไร.pdf
1 devops คืออะไร.pdf 1 devops คืออะไร.pdf
 
angular fundamentals.pdf angular fundamentals.pdf
angular fundamentals.pdf angular fundamentals.pdfangular fundamentals.pdf angular fundamentals.pdf
angular fundamentals.pdf angular fundamentals.pdf
 
mean stack mean stack mean stack mean stack
mean stack mean stack  mean stack  mean stackmean stack mean stack  mean stack  mean stack
mean stack mean stack mean stack mean stack
 
pinia.pdf
pinia.pdfpinia.pdf
pinia.pdf
 
nuxt-rendering-modes.pdf
nuxt-rendering-modes.pdfnuxt-rendering-modes.pdf
nuxt-rendering-modes.pdf
 
zustand.pdf
zustand.pdfzustand.pdf
zustand.pdf
 
tanstack-query.pdf
tanstack-query.pdftanstack-query.pdf
tanstack-query.pdf
 
nuxt-fundamentals.pdf
nuxt-fundamentals.pdfnuxt-fundamentals.pdf
nuxt-fundamentals.pdf
 
vue-components.pdf
vue-components.pdfvue-components.pdf
vue-components.pdf
 
vue-reactivity.pdf
vue-reactivity.pdfvue-reactivity.pdf
vue-reactivity.pdf
 

Recently uploaded

SOCIAL AND HISTORICAL CONTEXT - LFTVD.pptx
SOCIAL AND HISTORICAL CONTEXT - LFTVD.pptxSOCIAL AND HISTORICAL CONTEXT - LFTVD.pptx
SOCIAL AND HISTORICAL CONTEXT - LFTVD.pptxiammrhaywood
 
Incoming and Outgoing Shipments in 1 STEP Using Odoo 17
Incoming and Outgoing Shipments in 1 STEP Using Odoo 17Incoming and Outgoing Shipments in 1 STEP Using Odoo 17
Incoming and Outgoing Shipments in 1 STEP Using Odoo 17Celine George
 
Solving Puzzles Benefits Everyone (English).pptx
Solving Puzzles Benefits Everyone (English).pptxSolving Puzzles Benefits Everyone (English).pptx
Solving Puzzles Benefits Everyone (English).pptxOH TEIK BIN
 
Science 7 - LAND and SEA BREEZE and its Characteristics
Science 7 - LAND and SEA BREEZE and its CharacteristicsScience 7 - LAND and SEA BREEZE and its Characteristics
Science 7 - LAND and SEA BREEZE and its CharacteristicsKarinaGenton
 
18-04-UA_REPORT_MEDIALITERAСY_INDEX-DM_23-1-final-eng.pdf
18-04-UA_REPORT_MEDIALITERAСY_INDEX-DM_23-1-final-eng.pdf18-04-UA_REPORT_MEDIALITERAСY_INDEX-DM_23-1-final-eng.pdf
18-04-UA_REPORT_MEDIALITERAСY_INDEX-DM_23-1-final-eng.pdfssuser54595a
 
How to Configure Email Server in Odoo 17
How to Configure Email Server in Odoo 17How to Configure Email Server in Odoo 17
How to Configure Email Server in Odoo 17Celine George
 
Science lesson Moon for 4th quarter lesson
Science lesson Moon for 4th quarter lessonScience lesson Moon for 4th quarter lesson
Science lesson Moon for 4th quarter lessonJericReyAuditor
 
CARE OF CHILD IN INCUBATOR..........pptx
CARE OF CHILD IN INCUBATOR..........pptxCARE OF CHILD IN INCUBATOR..........pptx
CARE OF CHILD IN INCUBATOR..........pptxGaneshChakor2
 
Sanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdfSanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdfsanyamsingh5019
 
Blooming Together_ Growing a Community Garden Worksheet.docx
Blooming Together_ Growing a Community Garden Worksheet.docxBlooming Together_ Growing a Community Garden Worksheet.docx
Blooming Together_ Growing a Community Garden Worksheet.docxUnboundStockton
 
भारत-रोम व्यापार.pptx, Indo-Roman Trade,
भारत-रोम व्यापार.pptx, Indo-Roman Trade,भारत-रोम व्यापार.pptx, Indo-Roman Trade,
भारत-रोम व्यापार.pptx, Indo-Roman Trade,Virag Sontakke
 
Computed Fields and api Depends in the Odoo 17
Computed Fields and api Depends in the Odoo 17Computed Fields and api Depends in the Odoo 17
Computed Fields and api Depends in the Odoo 17Celine George
 
Proudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.pptxProudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.pptxthorishapillay1
 
Alper Gobel In Media Res Media Component
Alper Gobel In Media Res Media ComponentAlper Gobel In Media Res Media Component
Alper Gobel In Media Res Media ComponentInMediaRes1
 
ENGLISH5 QUARTER4 MODULE1 WEEK1-3 How Visual and Multimedia Elements.pptx
ENGLISH5 QUARTER4 MODULE1 WEEK1-3 How Visual and Multimedia Elements.pptxENGLISH5 QUARTER4 MODULE1 WEEK1-3 How Visual and Multimedia Elements.pptx
ENGLISH5 QUARTER4 MODULE1 WEEK1-3 How Visual and Multimedia Elements.pptxAnaBeatriceAblay2
 
Biting mechanism of poisonous snakes.pdf
Biting mechanism of poisonous snakes.pdfBiting mechanism of poisonous snakes.pdf
Biting mechanism of poisonous snakes.pdfadityarao40181
 
_Math 4-Q4 Week 5.pptx Steps in Collecting Data
_Math 4-Q4 Week 5.pptx Steps in Collecting Data_Math 4-Q4 Week 5.pptx Steps in Collecting Data
_Math 4-Q4 Week 5.pptx Steps in Collecting DataJhengPantaleon
 
Introduction to AI in Higher Education_draft.pptx
Introduction to AI in Higher Education_draft.pptxIntroduction to AI in Higher Education_draft.pptx
Introduction to AI in Higher Education_draft.pptxpboyjonauth
 
Hybridoma Technology ( Production , Purification , and Application )
Hybridoma Technology  ( Production , Purification , and Application  ) Hybridoma Technology  ( Production , Purification , and Application  )
Hybridoma Technology ( Production , Purification , and Application ) Sakshi Ghasle
 

Recently uploaded (20)

SOCIAL AND HISTORICAL CONTEXT - LFTVD.pptx
SOCIAL AND HISTORICAL CONTEXT - LFTVD.pptxSOCIAL AND HISTORICAL CONTEXT - LFTVD.pptx
SOCIAL AND HISTORICAL CONTEXT - LFTVD.pptx
 
Model Call Girl in Bikash Puri Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in Bikash Puri  Delhi reach out to us at 🔝9953056974🔝Model Call Girl in Bikash Puri  Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in Bikash Puri Delhi reach out to us at 🔝9953056974🔝
 
Incoming and Outgoing Shipments in 1 STEP Using Odoo 17
Incoming and Outgoing Shipments in 1 STEP Using Odoo 17Incoming and Outgoing Shipments in 1 STEP Using Odoo 17
Incoming and Outgoing Shipments in 1 STEP Using Odoo 17
 
Solving Puzzles Benefits Everyone (English).pptx
Solving Puzzles Benefits Everyone (English).pptxSolving Puzzles Benefits Everyone (English).pptx
Solving Puzzles Benefits Everyone (English).pptx
 
Science 7 - LAND and SEA BREEZE and its Characteristics
Science 7 - LAND and SEA BREEZE and its CharacteristicsScience 7 - LAND and SEA BREEZE and its Characteristics
Science 7 - LAND and SEA BREEZE and its Characteristics
 
18-04-UA_REPORT_MEDIALITERAСY_INDEX-DM_23-1-final-eng.pdf
18-04-UA_REPORT_MEDIALITERAСY_INDEX-DM_23-1-final-eng.pdf18-04-UA_REPORT_MEDIALITERAСY_INDEX-DM_23-1-final-eng.pdf
18-04-UA_REPORT_MEDIALITERAСY_INDEX-DM_23-1-final-eng.pdf
 
How to Configure Email Server in Odoo 17
How to Configure Email Server in Odoo 17How to Configure Email Server in Odoo 17
How to Configure Email Server in Odoo 17
 
Science lesson Moon for 4th quarter lesson
Science lesson Moon for 4th quarter lessonScience lesson Moon for 4th quarter lesson
Science lesson Moon for 4th quarter lesson
 
CARE OF CHILD IN INCUBATOR..........pptx
CARE OF CHILD IN INCUBATOR..........pptxCARE OF CHILD IN INCUBATOR..........pptx
CARE OF CHILD IN INCUBATOR..........pptx
 
Sanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdfSanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdf
 
Blooming Together_ Growing a Community Garden Worksheet.docx
Blooming Together_ Growing a Community Garden Worksheet.docxBlooming Together_ Growing a Community Garden Worksheet.docx
Blooming Together_ Growing a Community Garden Worksheet.docx
 
भारत-रोम व्यापार.pptx, Indo-Roman Trade,
भारत-रोम व्यापार.pptx, Indo-Roman Trade,भारत-रोम व्यापार.pptx, Indo-Roman Trade,
भारत-रोम व्यापार.pptx, Indo-Roman Trade,
 
Computed Fields and api Depends in the Odoo 17
Computed Fields and api Depends in the Odoo 17Computed Fields and api Depends in the Odoo 17
Computed Fields and api Depends in the Odoo 17
 
Proudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.pptxProudly South Africa powerpoint Thorisha.pptx
Proudly South Africa powerpoint Thorisha.pptx
 
Alper Gobel In Media Res Media Component
Alper Gobel In Media Res Media ComponentAlper Gobel In Media Res Media Component
Alper Gobel In Media Res Media Component
 
ENGLISH5 QUARTER4 MODULE1 WEEK1-3 How Visual and Multimedia Elements.pptx
ENGLISH5 QUARTER4 MODULE1 WEEK1-3 How Visual and Multimedia Elements.pptxENGLISH5 QUARTER4 MODULE1 WEEK1-3 How Visual and Multimedia Elements.pptx
ENGLISH5 QUARTER4 MODULE1 WEEK1-3 How Visual and Multimedia Elements.pptx
 
Biting mechanism of poisonous snakes.pdf
Biting mechanism of poisonous snakes.pdfBiting mechanism of poisonous snakes.pdf
Biting mechanism of poisonous snakes.pdf
 
_Math 4-Q4 Week 5.pptx Steps in Collecting Data
_Math 4-Q4 Week 5.pptx Steps in Collecting Data_Math 4-Q4 Week 5.pptx Steps in Collecting Data
_Math 4-Q4 Week 5.pptx Steps in Collecting Data
 
Introduction to AI in Higher Education_draft.pptx
Introduction to AI in Higher Education_draft.pptxIntroduction to AI in Higher Education_draft.pptx
Introduction to AI in Higher Education_draft.pptx
 
Hybridoma Technology ( Production , Purification , and Application )
Hybridoma Technology  ( Production , Purification , and Application  ) Hybridoma Technology  ( Production , Purification , and Application  )
Hybridoma Technology ( Production , Purification , and Application )
 

Babel Coder JavaScript recap template literals fetch axios

  • 2. Babel Coder TEMPLATE Template String var myStr1 = 'Hello World' var myStr2 = "Hello World" var myStr3 = "HellonWorld" var myStr4 = ` Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ` var myStr5 = `${myStr1} Krub`
  • 3. Babel Coder LET AND CONST function foo() { let x = 1 x = 2 } foo() function foo() { const x = 1 x = 2 } foo()
  • 4. Babel Coder PROPERTY SHORTHAND const x = 10 const y = 20 const obj = { x: x, y: y } const obj = { x, y } Property Shorthand (ES6+)
  • 5. Babel Coder DESTRUCTURING let person = { age: 24, gender: 'male', name: { fi rstName: ' fi rstName', lastName: 'lastName' } } let age = person.age let gender = person.gender let name = person.name let fi rstName = name. fi rstName let lastName = name.lastName let { age, gender, name } = person let { fi rstName, lastName } = name let { age, gender, name: { fi rstName, lastName } } = person
  • 6. Babel Coder SPREAD OPERATORS const obj1 = { a: 1, b: 2 } const obj2 = { c: 3, d: 4 } console.log({ ...obj1, ...obj2 }) const arr1 = [1, 2, 3] const arr2 = [4, 5, 6] console.log([...arr1, ...arr2])
  • 7. Babel Coder EXAMPLE 1 Math.min(12, 14, 8, 17, 21, 9) // 8 const nums = [12, 14, 8, 17, 21, 9] Math.min(...nums)
  • 8. Babel Coder ARROW FUNCTION function foo(a) { return a + 1 } const foo = (a) => { return a + 1 } const foo = a => { return a + 1 } const foo = a => a + 1 const foo = a => let b = a + 1 Must be expression
  • 9. OPTIONAL CHAINING const person = { name: 'Somchai', age: 24, socials: { facebook: 'somchai24' } } <div> <div>{person?.socials?.facebook}</div> </div> <div> <div>{person?.tel?.phone}</div> </div>
  • 10. ES MODULE - NAMED EXPORTS export const DEFAULT_COLOR = 'white' export function walk() { console.log('Walking...') } { DEFAULT_COLOR: 'white', walk() { console.log('Walking...') } } dog.js main.js syntax: 1 import * as lib from './dog.js' lib.DEFAULT_COLOR // white lib.walk() // Walking... main.js syntax: 2 import { DEFAULT_COLOR, walk } from './dog.js'
  • 11. ES MODULE - DEFAULT EXPORT circle.js main.js syntax export default class Circle { area() { } } import Circle from './circle.js'
  • 12. ES MODULE - BOTH circle.js export const PI = 3.14 export default class Circle { area() { } } main.js syntax import Circle, { PI } from './circle.js'
  • 13. Babel Coder FETCHING fetch('/api/v1/articles/1', function(response) { fetch('/api/v1/users/' + response.authorId, function(response) { // ... }) }) fetch('/api/v1/articles/1') .then(function(response) { return fetch('/api/v1/users/' + response.authorId) }) .then(function() { })
  • 14. Babel Coder AXIOS import axios from 'axios' axios.get('/articles') .then(res => console.log(res.data)) axios.post('/articles', { title: 'Title#1', content: 'Content#1' }) .then(res => console.log(res.data)) GET POST
  • 15. Babel Coder AXIOS BASE URL AND INTERCEPTORS axios.defaults.baseURL = 'https://api.example.com' axios.defaults.headers.common['Authorization'] = AUTH_TOKEN // Interceptors axios.interceptors.response.use( response => response, error => { if (error.response.status === 401) { auth.clearAuth() router.replace('/signin') } return Promise.reject(error.response) } )
  • 16. ASYNC / AWAIT promise.then(function(result) { console.log(result) }).catch(function(error) { console.log(error) }) async function doAsync() { try { const result = await promise console.log(result) } catch(error) { console.log(error) } }
  • 17. EXAMPLE 1 Fetch content from URL: https://jsonplaceholder.typicode.com/todos import axios from 'axios' async function fetchPosts() { const res =await axios.get(URL) console.log(res.data) console.log(res.status) // 200 } fetchPosts() HTTP GET HTTP POST import axios from 'axios' async function createPost() { const res =await axios.post( URL, { title: 'Test', completed: true }) console.log(res.status) // 201 } createPost()
  • 18. WHAT IS FUNCTIONAL PROGRAMMING • Functional Programming is a programming paradigm. • It treats computation as the evaluation of mathematical functions. • Avoid changing state. • Eliminating side effects of function calls. • Declarative Style
  • 19. IMMUTABILITY const nums = [1, 2, 3] const nums2 = [6, 7] nums.concat() nums.slice() nums.concat(4) // [1, 2, 3, 4] nums.slice(0, 2); // [1, 2] [...nums, 4, ...nums2] // [1, 2, 3, 4, 6, 7] const object = { a: 1, b: 2 } // {"a":1,"b":2,"c":3,"d":4} console.log({...object, c: 3, d: 4 }) // {"a":1,"b":9} const newObject = { b: 9 } console.log({ ...object, ...newObject }) // {"a":1,"b":9} const key = 'b' console.log({ ...object, [key]: 9}) 1
  • 20. MAP const nums = [1, 2, 3] console.log(nums.map(num => num * 2)) // [2, 4, 6] const students = [ { id: 1, advisorId: 1 }, { id: 2, advisorId: 2 }, { id: 3, advisorId: 3 }, { id: 4, advisorId: 1 }, { id: 5, advisorId: 3 } ] console.log( students.map(student => student.advisorId === 1 ? { ...student, advisorId: 2 } : student ) ) // [{"id":1,"advisorId":2}, {"id":2,"advisorId":2}, {"id":3,"advisorId":3}, {"id":4,"advisorId":2}, {"id":5,"advisorId":3}] 2
  • 21. FILTER const students = [ { id: 1, advisorId: 1 }, { id: 2, advisorId: 2 }, { id: 3, advisorId: 3 }, { id: 4, advisorId: 1 }, { id: 5, advisorId: 3 } ] console.log( students.filter(student => student.advisorId === 1) ) // [{"id":1,"advisorId":1},{"id":4,"advisorId":1}] 3
  • 22. FIND / FIND INDEX const nums = [1, 2, 3, 4, 5] nums.find(num => num % 2 === 0) // 2 const nums = [1, 2, 3, 4, 5] nums.findIndex(num => num % 2 === 0) // 1 4
  • 24. Babel Coder SETUP 1 yarn init -y 2 yarn add -D tsc nodemon ts-node typescript eslint eslint-con g-prettier eslint-plugin-prettier prettier @typescript-eslint/parser @typescript-eslint/eslint-plugin 3 npx tsc —init 4 package.json "scripts": { "dev": "nodemon src/index.ts", "build": "tsc", "lint": "eslint '*/**/*.{js,ts}' --quiet -- fi x" },
  • 25. Babel Coder SETUP 5 .eslintrc.js module.exports = { parser: '@typescript-eslint/parser', parserOptions: { ecmaVersion: 2020, sourceType: 'module', }, settings: {}, extends: [ 'plugin:@typescript-eslint/recommended', 'prettier/@typescript-eslint', 'plugin:prettier/recommended', ], rules: {}, }; 6 .vscode/settings.json { "editor.tabSize": 2, "editor.codeActionsOnSave": { "source. fi xAll.eslint": true } }
  • 26. Babel Coder SETUP 7 .prettierrc { "trailingComma": "all", "singleQuote": true } 8 nodemon.json { "watch": ["src"], "ext": "ts", "exec": "ts-node" } 9 tscon fi g.json { "compilerOptions": { "target": "es5", "module": "commonjs", "lib": ["ES2020", "DOM"], "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true } }
  • 28. Babel Coder PRIMITIVE DATA TYPES • string • number • bigint • boolean • null • undefined • symbol
  • 29. Babel Coder PRIMITIVE DATA TYPES const num1: number = 10 const num2 = 20 const bool1: boolean = true const bool2 = false const str1: string = "hello" const str2 = "world"
  • 30. Babel Coder ANY AND UNKNOWN function next(num: number) { return num + 1; } let num: any = 10; num = 'hello'; next(num); num.toFixed(2); let num: unknown = 10; num = 'hello'; // Argument of type 'unknown' is not assignable to parameter of type 'number'. next(num); // Object is of type 'unknown'. num.toFixed(2); const num: unknown = 10; next(num); if (typeof num === 'number') { next(num); }
  • 31. Babel Coder LITERAL TYPES let str1: 'Hello' = 'Hello'; let str2: string = str1; // Type 'string' is not assignable to type '"Hello"'. str1 = str2; let str1 = 'Hello'; // string const str2 = 'Hello'; // Hello function permission(role: 'Admin' | 'Moderator' | 'Editor') { // do sth } permission('Admin'); let role = 'Editor'; // Argument of type 'string' is not assignable // to parameter of type '"Admin" | "Moderator" | "Editor"'. permission(role); permission(role as 'Editor');
  • 32. Babel Coder ARRAY let nums1: number[] = [1, 2, 3] // number[] let nums2: Array<number> = [1, 2, 3] // number[] let nums3 = [1, 2, 3] // number[] const nums4 = [1, 2, 3] // number[] const nums5: readonly number[] = [1, 2, 3] // readonly number[] const nums6: ReadonlyArray<number> = [1, 2, 3] // readonly number[] const nums7 = nums6 as number[]; // number[] const foo: string[] = []; // OK const a: never[] = []; // OK const b: never[] = [1, 2]; // Type 'number' is not assignable to type 'never'
  • 33. Babel Coder ENUM enum Role { Admin, Moderator, Editor, } const myRole: Role = Role.Admin; // 0 Role[0]; // Admin Role.Admin // 0 enum Role { Admin, Moderator, Editor, } enum Role { Admin = 'Admin', Moderator = 'Moderator', Editor = 'Editor', } Role.Admin; // Admin
  • 34. Babel Coder INTERFACES let person; // any person = { name: 'Somchai', age: 24, gender: 'male', }; interface Person { name: string; age: number; gender: string; } let person: Person; person = { name: 'Somchai', age: 24, gender: 'male', }; // Property 'gender' is missing in type // ‘{ name: string; age: number; }' // but required in type 'Person'. const person: Person = { name: 'Somchai', age: 24, }; const person: Person = { name: 'Somchai', age: 24, gender: 'male', };
  • 35. Babel Coder EXTENDING INTERFACES interface Website { url: string; } interface Article { title: string; content: string; } interface BlogPost extends Website, Article { view: number; } const post: BlogPost = { url: 'https://www.babelcoder.com/blog/articles/typescript-classes', title: 'การใ ช้ งานคลาสใน TypeScript', content: '...', view: 999, };
  • 36. Babel Coder READONLY AND OPTIONAL PROPERTIES interface Person { fi rstName: string; lastName: string; middleName?: string; readonly gender: 'Male' | 'Female'; } let somchai: Person = { fi rstName: 'Somchai', lastName: 'Haha', gender: 'Male', }; // Cannot assign to 'gender' because // it is a read-only property. somchai.gender = 'Female';
  • 37. Babel Coder TYPE ALIAS interface Person { name: string; age: number; gender: string; } type Person = { name: string; age: number; gender: string; }; interface Website { url: string; } interface Article { title: string; content: string; } interface BlogPost extends Website, Article { view: number; } type Website = { url: string; }; type Article = { title: string; content: string; }; type BlogPost = Website & Article & { view: number; };
  • 38. Babel Coder FUNCTION TYPES function getFullName( fi rstName, lastName) { return `${ fi rstName} ${lastName}`; } function getFullName( fi rstName: string, lastName: string): string { return `${ fi rstName} ${lastName}`; } const getFullName = function ( fi rstName: string, lastName: string): string { return `${ fi rstName} ${lastName}`; };
  • 39. Babel Coder FUNCTION TYPES const getFullName = ( fi rstName, lastName) => { return `${ fi rstName} ${lastName}`; }; const getFullName = ( fi rstName: string, lastName: string): string => { return `${ fi rstName} ${lastName}`; }; type GetFullNameFn = ( fi rstName: string, lastName: string) => string; const getFullName: GetFullNameFn = ( fi rstName, lastName) => { return `${ fi rstName} ${lastName}`; };
  • 40. Babel Coder CONST ASSERTIONS // const theme: { // colors: { // amethyst: "#9b59b6"; // carrot: string; // }; // } const theme = { colors: { amethyst: '#9b59b6' as const, carrot: '#e67e22', }, }; // const theme: { // colors: { // amethyst: string; // carrot: string; // }; // } const theme = { colors: { amethyst: '#9b59b6', carrot: '#e67e22', }, }; // const theme: { // readonly colors: { // readonly amethyst: "#9b59b6"; // readonly carrot: "#e67e22"; // }; // } const theme = { colors: { amethyst: '#9b59b6', carrot: '#e67e22', }, } as const;
  • 41. Babel Coder TYPEOF const user = { name: 'Somchai' }; console.log(typeof user); // 'object' // type User = { // name: string; // } type User = typeof user;
  • 42. Babel Coder UNION TYPES type Printable = string | string[]; const text: Printable = 'my message'; function format(thing: Printable): string { if (Array.isArray(thing)) return thing.join(', '); return thing; }
  • 43. Babel Coder INTERSECTION TYPES interface Identity { id: number; name: string; } interface Contact { email: string; phone: string; address: string; } type Employee = Identity & Contact; const somchai: Employee = { id: 11001, name: 'Somchai', email: 'somchai@haha.com', phone: '082-111-1111', address: '111/11', };
  • 44. Babel Coder CLASSES class BankAccount { static interestRate = 3.5; balance: number; constructor(balance: number) { this.balance = balance; } getInterest() { return this.balance * BankAccount.interestRate; } } const myAcc1 = new BankAccount(20); const myAcc2 = new BankAccount(30); myAcc1.balance; // 20 myAcc1.getInterest(); // 70 myAcc1 balance: 20 getInterest myAcc2 balance: 30 getInterest getInterest 3.5 BankAccount
  • 45. Babel Coder ACCESS MODIFIERS class BankAccount { protected balance: number; constructor(balance: number) { this.balance = balance; } withdraw(amount: number) { if (amount <= this.balance) this.balance -= amount; } deposit(amount: number) { if (amount > 0) this.balance += amount; } } class SavingAccount extends BankAccount { static readonly interestRate = 3.5; private readonly debitCard: number; constructor(balance: number, debitCard: number) { super(balance); this.debitCard = debitCard; } getInterest() { return this.balance * SavingAccount.interestRate; } }
  • 46. Babel Coder PARAMETER PROPERTIES class BankAccount { constructor(protected balance: number) {} withdraw(amount: number) { if (amount <= this.balance) this.balance -= amount; } deposit(amount: number) { if (amount > 0) this.balance += amount; } } class SavingAccount extends BankAccount { static interestRate = 3.5; constructor( balance: number, private readonly debitCard: number) { super(balance); } getInterest() { return this.balance * SavingAccount.interestRate; } }
  • 47. Babel Coder KEYWORD NEW class Person { constructor() {} } function get<T>(ctor: Factory<T>) { return new ctor(); } // const person: Person const person = get(Person); interface Factory<T> { new (...args: any[]): T; } // OR type Factory<T> = new (...args: any[]) => T;
  • 48. Babel Coder GENERIC FUNCTIONS function lastNum(arr: number[], count: number) { return arr.slice(arr.length - count); } lastNum([1, 2, 3, 4, 5], 3); // [3, 4, 5] function lastStr(arr: string[], count: number) { return arr.slice(arr.length - count); } lastStr(['A', 'B', 'C', 'D', 'E'], 2); // ['D', 'E'] function last<T>(arr: T[], count: number) { return arr.slice(arr.length - count); } const last = <T>(arr: T[], count: number) => { return arr.slice(arr.length - count); }; last<string>(['A', 'B', 'C', 'D', 'E'], 2); last(['A', 'B', 'C', 'D', 'E'], 2);
  • 49. Babel Coder GENERIC TYPES AND INTERFACES const head = <T>(arr: T[]) => arr[0]; const tail = <T>(arr: T[]) => arr[arr.length - 1]; type GetItem<T> = (arr: T[]) => T; interface GetItem<T> { (arr: T[]): T; } const option: GetItem<number> = head; option([1, 2, 3]); function getItem<T>(list: T[], fn: GetItem<T>): T { return fn(list); } getItem([1, 2, 3], head); // 1 getItem([1, 2, 3], tail); // 3
  • 51. Babel Coder RECORD type MyRecord<T extends string | number | symbol, U> = { [K in T]: U; }; type keys = 'name' | 'address'; // type MyPerson = { // name: string; // address: string; // } type MyPerson = MyRecord<keys, string>; type Person = Record<keys, string>;
  • 52. Babel Coder PICK AND OMIT type MyPick<T, K extends keyof T> = { [P in K]: T[P]; }; type Person = { name: string; age: number; address: string; }; // type NameAndAge = { // name: string; // age: number; // } type MyNameAndAge = MyPick<Person, 'name' | 'age'>; type NameAndAge = Pick<Person, 'name' | 'age'>; type MyOmit<T, K extends string | number | symbol> = Pick< T, Exclude<keyof T, K> >; type Person = { name: string; age: number; address: string; }; // type MyAddress = { // address: string; // } type MyAddress = MyOmit<Person, 'name' | 'age'>; type Address = Omit<Person, 'name' | 'age'>;
  • 53. Babel Coder REQUIRED AND PARTIAL type MyPartial<T> = { [K in keyof T]?: T[K]; }; type Person = { name: string; age: number; address: string; }; // type MyPartialPerson = { // name?: string | unde fi ned; // age?: number | unde fi ned; // address?: string | unde fi ned; // } type MyPartialPerson = MyPartial<Person>; type PartialPerson = Partial<Person>; type MyRequired<T> = { [K in keyof T]-?: T[K]; }; type Person = { name: string; age: number; address: string; }; // type MyRequiredPerson = { // name: string; // age: number; // address: string; // } type MyRequiredPerson = MyRequired<Person>; type RequiredPerson = Required<Person>;
  • 54. Babel Coder READONLY type MyReadonly<T> = { readonly [K in keyof T]: T[K]; }; type Person = { name: string; age: number; address: string; }; // type MyReadOnlyPerson = { // readonly name: string; // readonly age: number; // readonly address: string; // } type MyReadOnlyPerson = MyReadonly<Person>; type ReadOnlyPerson = Readonly<Person>;
  • 56. Babel Coder DEFINITELY TYPED // Could not fi nd a declaration fi le for module 'lodash'. import lodash from 'lodash'; yarn add @types/lodash yarn add @types/absinthe__socket
  • 57. Babel Coder A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES Declarative Component-Based Learn Once, Write Anywhere
  • 58. Babel Coder IMPERATIVE VS DECLARATIVE HTML <div id="counter">0</div> <button id="incBtn">inc</button> JavaScript let count = 0 const incBtn = document.getElementById("incBtn") const counter = document.getElementById("counter") incBtn.onclick = function() { counter.textContent = ++count } JSX function Counter() { const [count, setCount] = useState(0) return ( <> <div>{count}</div> <button onClick={() => setCount(count + 1)}>inc</button> </> ) } Imperative Declarative
  • 59. Babel Coder COMPONENT-BASED DESIGN App Jumbotron Header PostList PostItem PostItem PostItem
  • 60. Babel Coder React React Native React Native for Windows + macOS
  • 61. Babel Coder COMPOSITION App function App() { return ( <> <SearchForm></SearchForm> <SearchResults></SearchResults> </> ) } function SearchForm() { return <div>SearchForm</div> } function SearchResults() { return <div>SearchResults</div> } SearchForm SearchResults
  • 62. Babel Coder STATE App import React, { useState } from 'react' function App() { const [titles, setTitles] = useState(initialTitles) return ( <> <SearchForm></SearchForm> <SearchResults></SearchResults> </> ) } useState returns a pair: the current state value and a function that lets you update it. The only argument to useState is the initial state. const initialTitles = [ 'Reactive Programming คื ออะไร', 'เป รี ยบเ ที ยบ React, Vue และ Angular', 'Server Rendering' ]
  • 63. Babel Coder PROPS App SearchResults function App() { const [titles, setTitles] = useState(initialTitles) return ( <> <SearchForm></SearchForm> <SearchResults titles={titles}></SearchResults> </> ) } function SearchResults(props) { return <div>{props.titles[0]}</div> } App SearchForm SearchResults titles titles props
  • 64. Babel Coder DATA TRANSFORMATION SearchResults function SearchResults(props) { return ( <ul> {props.titles.map((title, index) => ( <li key={index}>{title}</li> ))} </ul> ) } Reactive Programming คื ออะไร เป รี ยบเ ที ยบ React, Vue และ Angular Server Rendering Reactive Programming คื ออะไร เป รี ยบเ ที ยบ React Vue และ Angular Server Rendering li tag
  • 65. Babel Coder EVENT HANDLER App function SearchForm() { const [input, setInput] = useState('') const onInputChange = event => setInput(event.target.value) return ( <input type="text" value={input} onChange={onInputChange} /> ) } state [input setInput] Input Tag value onChange event.target.value
  • 66. Babel Coder EVENTS Touch & Mouse Keyboard Other
  • 67. Babel Coder PARENT-CHILD COMMUNICATION App function App() { const [titles, setTitles] = useState(initialTitles) const search = keyword => { const result = keyword === '' ? initialTitles : titles. fi lter(title => title.includes(keyword)) setTitles(result) } return ( <> <SearchForm onSubmit={search}></SearchForm> <SearchResults titles={titles}></SearchResults> </> ) } SearchForm function SearchForm(props) { const [input, setInput] = useState('') const onInputChange = event => { const input = event.target.value setInput(input) props.onSubmit(input) } return ( <input type="text" value={input} onChange={onInputChange} /> }
  • 68. Babel Coder PARENT-CHILD COMMUNICATION Reactive Programming คื ออะไร เป รี ยบเ ที ยบ React Vue และ Angular Server Rendering App SearchForm SearchResults titles onChange action up data down
  • 69. Babel Coder COMPONENT LIFECYCLE Component state render Hello World Mounting Mounted Hello Thailand Updating Unmounting Updated Unmounted props
  • 70. Babel Coder REACT HOOKS Hooks are functions that let you “hook into” React state and lifecycle features from function components. RULES OF HOOKS • Only call Hooks at the top level. Don’t call Hooks inside loops, conditions, or nested functions. • Only call Hooks from React function components. Don’t call Hooks from regular JavaScript functions (except custom hooks).
  • 71. Babel Coder STATE MANAGEMENT import React, { useState } from 'react' function App() { const [count, setCount] = useState(0) return ( <button onClick={() => setCount(count + 1)}> {count} </button> ) } 0 count onClick setCount
  • 72. Babel Coder LIFECYCLE MANAGEMENT function App() { const [count, setCount] = useState(0) useE ff ect(() => { const timer = setInterval(() => setCount(count + 1), 1000) return () => clearInterval(timer) }, [count]) return <div>{count}</div> } Call after mounted and updated Call before unmounted
  • 73. Babel Coder EXAMPLE 1 App function App() { const [msg, setMsg] = useState('') return ( <> <input type="text" value={msg} onChange={event => setMsg(event.target.value)} /> <Counter msg={msg}></Counter> </> ) } Counter function Counter({ msg }) { const [count, setCount] = useState(0) useE ff ect(() => { const timer = setInterval(() => setCount(count + 1), 1000) document.title = `${msg} ${count}` return () => clearInterval(timer) }, [count, msg]) return <div>{count}</div> }
  • 74. Babel Coder MANAGE MUTABLE REF OBJECT useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component. WHEN TO USE REF • Managing focus, text selection, or media playback. • Integrating with third-party DOM libraries. • Triggering imperative animations.
  • 75. Babel Coder REF TO ELEMENT function App() { const inputEl = useRef(null) return ( <> <input type="text" ref={inputEl} /> <button onClick={() => inputEl.current.focus()}>Focus</button> </> ) }
  • 76. Babel Coder MUTABLE OBJECT function App() { const counter = useRef(0) const increase = () => { counter.current += 1 console.log(counter.current) } return ( <> <div>{counter.current}</div> <button onClick={increase}>Focus</button> </> ) } Changed Unchanged • A ref created with useRef will be created only when the component has been mounted and preserved during the full lifecycle. • Refs can be used for accessing DOM nodes or React elements, and for keeping mutable variables (like instance variables in class components). • Updating a ref is a side effect so it should be done only inside an useEffect (or useLayoutEffect) or inside an event handler.
  • 77. Babel Coder CUSTOM HOOKS function useInterval(initialCount) { const [count, setCount] = useState(initialCount) useE ff ect(() => { const timer = setInterval(() => setCount(count + 1), 1000) return () => clearInterval(timer) }) return count } function App() { const count = useInterval(0) return <div>{count}</div> }
  • 78. Babel Coder HOOKS AND LIFECYCLE Mounting Updating Unmounting render React updates DOM and ref Layout Cleanup Layout Effect Effect Cleanup Effect Render Phase Pure, no side e ff ect. May be paused, aborted or restarted by React. Reconciliation Phase Handled by React Layout Phase Can work with DOM, but blocks the rendering Commit Phase Can work with DOM, run side e ff ects, schedule updates
  • 79. Babel Coder CONTEXT const themes = { light: { foreground: '#000000', background: '#eeeeee' }, dark: { foreground: '# ff ff ff ', background: '#222222' } } function App() { const [theme, setTheme] = useState(themes.light) return <AddressBook theme={theme}></AddressBook> } function AddressBook({ theme }) { return <AddressList theme={theme}></AddressList> } function AddressList({ theme }) { return <div style={{ background: theme.background }}></div> }
  • 81. Babel Coder CONTEXT import { createContext } from 'react' export const themes = { light: { foreground: '#000000', background: '#eeeeee' }, dark: { foreground: '# ff ff ff ', background: '#222222' } } export default createContext(themes.light) lib/theme.js
  • 82. Babel Coder CONTEXT import ThemeContext, { themes } from './lib/theme' import AddressBook from './AddressBook' export default function App() { const [theme, setTheme] = useState(themes.light) const switchTheme = () => { setTheme(theme === themes.light ? themes.dark : themes.light) } return ( <ThemeContext.Provider value={theme}> <button onClick={switchTheme}>Switch Theme</button> <AddressBook></AddressBook> </ThemeContext.Provider> ) } function AddressList({ addresses }) { return ( <ThemeContext.Consumer> {theme => ( <ul style={{ background: theme.background, color: theme.foreground }}> {addresses.map(({ id, address }) => ( <li key={id}>{address}</li> ))} </ul> )} </ThemeContext.Consumer> ) } App AddressList
  • 83. Babel Coder CONTEXT AddressList function AddressList({ addresses }) { const theme = useContext(ThemeContext) return ( <ul style={{ background: theme.background, color: theme.foreground }}> {addresses.map(({ id, address }) => ( <li key={id}>{address}</li> ))} </ul> ) }
  • 85. Babel Coder EXPRESS import express from 'express' const app = express() app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(3000, () => console.log(`App listening on http://0.0.0.0:3000`) )
  • 87. Babel Coder RESTFUL • Stands for “Representational State Transfer” • RESTful Web Services are one way of providing interoperability between computer systems on the Internet.
  • 88. Babel Coder TRADITIONAL WEB ARCHITECTURES Server Presentation Application Persistence Browser
  • 96. Babel Coder HTTP STATUS CODES CODE STATUS 1xx Informational responses 2xx Success 3xx Redirection 4xx Client Errors 5xx Server Errors
  • 97. Babel Coder HTTP STATUS CODES CODE STATUS 200 OK 201 Created 204 No Content 401 Unauthorized 404 Not Found 405 Method Not Allowed 422 Unprocessable Entity 500 Internal Server Error
  • 99. Babel Coder MODEL-VIEW-CONTROLLER Controller View Model Request UI Logic Business Logic Manipulate DB Dispatch Router
  • 101. Babel Coder EXPRESS import express from 'express' const app = express() app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(3000, () => console.log(`App listening on http://0.0.0.0:3000`) )
  • 102. Babel Coder MIDDLEWARE app = express() app.use(function (req, res, next) { console.log('Time:', Date.now()) next() }) app.use(function (err, req, res, next) { console.error(err.stack) res.status(500).send('Something broke!') })
  • 103. Babel Coder ROUTE-LEVEL MIDDLEWARE const app = express() const router = express.Router() router.get( '/', (req, res) => res.send('Articles') ) router.post( '/', (req, res) => res.send(req.body.title) ) app.use('/articles', router) GET /articles POST /articles import bodyParser from 'body-parser' app.use(bodyParser.json())
  • 104. Babel Coder NAMED PARAMETERS app = express() app.get( '/articles/:id', (req, res) => res.send(req.params.id) )
  • 105. Babel Coder BODY VALIDATOR const bodyValidator = <T extends Type<object>>(Dto: T): RequestHandler => async (req, _res, next) => { const dto = plainToInstance(Dto, req.body, { strategy: 'excludeAll' }); const errors = await validate(dto); if (errors.length > 0) return next(new ValidationError(errors)); req.body = dto; next(); }; export const register: RequestHandler[] = [ bodyValidator(SignUpFormDto), authenticator.signUp, async (req, res) => { res.status(HTTP_STATUSES.CREATED).json(new UserResponseDto(req.user)); }, ]; export class SignUpFormDto { @Expose() @IsEmail() email: string; @Expose() @Length(8) password: string; @Expose() name: string; } import { ValidationError as Err } from 'class-validator'; export class ValidationError extends Error { constructor(public errors: Err[]) { super('Validation Error'); } }
  • 106. Babel Coder RESPONSE TRANSFORMER const responseTransformer: RequestHandler = (_req, res, next) => { const oldJson = res.json; res.json = (body) => { if ('errors' in body) return oldJson.call(res, body); return oldJson.call( res, instanceToPlain(body, { strategy: 'excludeAll', }) ); }; next(); }; export class UserResponseDto { @Expose() name: string; @Expose() email: string; @Expose() avatar: string; @Expose() role: Role; constructor(user: User) { Object.assign(this, user); } }
  • 107. Babel Coder ERROR HANDLER const errorHandler: ErrorRequestHandler = (err, _req, res, next) => { if (err instanceof ValidationError) { res.status(HTTP_STATUSES.BAD_REQUEST).json({ errors: err.errors }); } if (err instanceof QueryFailedError) { res.status(HTTP_STATUSES.BAD_REQUEST).json({ errors: err.message }); } next(err); };
  • 108. Babel Coder TYPEORM export const AppDataSource = new DataSource({ type: 'mssql', host: con fi g.database.host, port: con fi g.database.port, username: con fi g.database.username, password: con fi g.database.password, database: con fi g.database.name, synchronize: false, logging: true, subscribers: [], entities: [User], migrations, extra: { trustServerCerti fi cate: true, trustedConnection: true, }, options: { useUTC: true, encrypt: true, }, }); @Entity() export class User { @PrimaryGeneratedColumn() id: number; @Column({ unique: true }) name: string; @Column({ unique: true }) email: string; @Column() password: string; @Column({ type: 'int', default: Role.MEMBER, }) role: Role; @Column({ nullable: true }) avatar?: string; @Column({ nullable: true, unique: true }) refreshToken?: string; @CreateDateColumn() createdAt: Date; @UpdateDateColumn() updatedAt: Date; @BeforeInsert() async hashPassword() { const hash = await bcrypt.hash(this.password, 10); this.password = hash; } isValidPassword(password: string) { return bcrypt.compare(password, this.password); } } const migrations = [ CreateUserTable1677496221672, ]; export default migrations;
  • 109. Babel Coder MIGRATION project.json { "targets": { "migration:create": { "executor": "nx:run-commands", "options": { "envFile": "apps/api/.env", "command": "npm run typeorm migration:create -- apps/api/src/data/migration/{args.name} -- -d apps/api/src/data/data-source.ts" } }, "migration:generate": { "executor": "nx:run-commands", "options": { "envFile": "apps/api/.env", "command": "npm run typeorm migration:generate -- -d apps/api/src/data/data-source.ts apps/api/src/data/migration/{args.name}" } }, "migration:run": { "executor": "nx:run-commands", "options": { "envFile": "apps/api/.env", "command": "npm run typeorm migration:run -- -d apps/api/src/data/data-source.ts" } }, "migration:revert": { "executor": "nx:run-commands", "options": { "envFile": "apps/api/.env", "command": "npm run typeorm migration:revert -- -d apps/api/src/data/data-source.ts" } }, }, "tags": [] } nx run api:migration:generate --name CreateUserTable nx run api:migration:run nx run api:migration:revert nx run api:migration:create --name AddRefreshTokenToUserTable
  • 111. Babel Coder AUTHENTICATION & AUTHORIZATION Authentication Articles Authorization Authentication is the process of ascertaining that somebody really is who he claims to be. Authorization refers to rules that determine who is allowed to do what.
  • 113. Babel Coder JSON WEB TOKEN <HEADER>.<PAYLOAD>.<SIGNATURE> JSON Web Token (JWT) is a JSON-based open standard (RFC 7519) for creating access tokens that assert some number of claims. Header { "alg": "HS256", "typ": "JWT" } base64UrlEncode eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 Payload { "sub": "1234567890", "name": "John Doe", "admin": true } base64UrlEncode eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI 6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9 Signature HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret )
  • 114. Babel Coder PAYLOAD Subject sub This holds the identifier for the token Issued At iat When the token was issued (unix timestamp) Expiry exp The token expiry date (unix timestamp) Issuer iss The issuer of the token
  • 115. Babel Coder AUTH ROUTING router.route('/auth'); router.post('/auth/sign-up', authController.register); router.post('/auth/sign-in', authController.login); router.get('/auth/pro fi le', authController.getPro fi le); router.patch('/auth/pro fi le', authController.updatePro fi le); router.post('/auth/refresh-token', authController.refreshToken); router.delete('/auth/sign-out', authController.signOut);
  • 116. Babel Coder MIDDLEWARE import { RequestHandler } from 'express'; import passport from 'passport'; import { compose } from 'compose-middleware'; export const signUp = passport.authenticate('sign-up', { session: false }); export const signIn = passport.authenticate('sign-in', { session: false }); export const accessToken: RequestHandler = compose([ passport.initialize({ userProperty: 'userFromToken' }), passport.authenticate('access-token', { session: false, }), ]); export const refreshToken = passport.authenticate('refresh-token', { session: false, }); import { RequestHandler } from 'express'; import { Role } from '../entity/User'; import { HTTP_STATUSES } from '../helper/http-statuses'; import { accessToken } from './authenticator'; export const permitFor = (roles: Role | Role[]) => [ accessToken, authorizer(roles), ]; const authorizer = (roles: Role | Role[]): RequestHandler => (req, res, next) => { const role = req.userFromToken.role; if (Array.isArray(roles) && roles.includes(role)) return next(); if (roles === role) return next(); res.sendStatus(HTTP_STATUSES.FORBIDDEN); }; export default authorizer; Authenticator Authorizer
  • 117. Babel Coder CONTROLLER const upload = multer({ dest: path.join(__dirname, 'uploads', 'users') }); export const register: RequestHandler[] = [ bodyValidator(SignUpFormDto), authenticator.signUp, async (req, res) => { res.status(HTTP_STATUSES.CREATED).json(new UserResponseDto(req.user)); }, ]; export const login: RequestHandler[] = [ authenticator.signIn, async (req, res, next) => { const user = req.user; req.login(user, { session: false }, async (error) => { if (error) return next(error); const { accessToken, refreshToken } = authService.signAndSaveTokens(user); return res .status(HTTP_STATUSES.CREATED) .json(new LoginResponseDto(accessToken, refreshToken, user)); }); }, ]; export const getPro fi le: RequestHandler[] = [ authenticator.accessToken, async (req, res) => { const user = await userService.getUserById(req.userFromToken.id); res.json(new UserResponseDto(user)); }, ]; export const updatePro fi le: RequestHandler[] = [ upload.single('avatar'), authenticator.accessToken, bodyValidator(UpdatePro fi leFormDto), async (req, res) => { const payload: UpdatePro fi leFormDto & { avatar: string } = req.body; if (req. fi le) payload.avatar = `uploads/users/${req. fi le. fi lename}`; const user = await userService.updateUser(req.userFromToken.id, payload); res.json(new UserResponseDto(user)); }, ]; export const refreshToken: RequestHandler[] = [ bodyValidator(RefreshTokenFormDto), authenticator.refreshToken, async (req, res) => { const user = req.user; const { accessToken, refreshToken } = authService.signAndSaveTokens(user); return res .status(HTTP_STATUSES.CREATED) .json(new LoginResponseDto(accessToken, refreshToken, user)); }, ]; export const signOut: RequestHandler[] = [ authenticator.accessToken, async (req, res) => { const user = req.user; await authService.signOut(user); res.json(new LoginResponseDto(null, null, user)); }, ];
  • 118. Babel Coder SERVICE const userRepository = AppDataSource.getRepository(User); export const signAndSaveTokens = (user: User) => { const accessToken = jwt.sign( { sub: user.id, role: user.role }, con fi g.secretKey.accessToken, { expiresIn: con fi g.expiresIn.accessToken } ); const refreshToken = jwt.sign( { sub: user.id }, con fi g.secretKey.accessToken, { expiresIn: con fi g.expiresIn.refreshToken } ); user.refreshToken = refreshToken; userRepository.save(user); return { accessToken, refreshToken }; }; export const signOut = async (user: User) => { user.refreshToken = null; await userRepository.save(user); }; const userRepository = AppDataSource.getRepository(User); export const getUserById = (id: number) => { return userRepository. fi ndOneBy({ id }); }; export const updateUser = async (id: number, form: Partial<User>) => { const currentUser = await getUserById(id); const currentAvatar = currentUser.avatar; const user = userRepository.create(form); if (user.password) await user.hashPassword(); await userRepository.update(id, user); if (user.avatar) { fs.rm(path.join(__dirname, currentAvatar), { force: true }); } return getUserById(id); }; auth user
  • 120. Babel Coder Delightful JavaScript Testing yarn test
  • 121. Babel Coder TESTING PYRAMID Unit Tests Integration Tests UI Tests ensure that modules which work well in isolation, also play well together. Unit testing • focus on testing small units • tested in isolation and independent of other units. • Unit tests should be fast. End-to-end testing is a methodology used to test whether the fl ow of an application is performing as designed from start to fi nish.
  • 123. Babel Coder The Testing Trophy https://twitter.com/kentcdodds/status/960723172591992832/photo/1 TypeScript / ESLint Cypress
  • 130. Babel Coder Unit Testing / Component Testing <ArticleList keyword={keyword} /> render( )
  • 131. Babel Coder TEST CASES function multiply(a, b) { return a * b } multiply.js describe(‘multiply', () => { it('multiplies two numbers correctly', () => { expect(multiply(3, 2)).toBe(6) }) }) multiply.test.js Matchers
  • 132. Babel Coder TRUTHINESS it('null', () => { const n = null expect(n).toBeNull() expect(n).toBeDe fi ned() expect(n).not.toBeUnde fi ned() expect(n).not.toBeTruthy() expect(n).toBeFalsy() }) it('zero', () => { const z = 0 expect(z).not.toBeNull() expect(z).toBeDe fi ned() expect(z).not.toBeUnde fi ned() expect(z).not.toBeTruthy() expect(z).toBeFalsy() })
  • 133. Babel Coder NUMBERS it('two plus two', () => { const value = 2 + 2 expect(value).toBeGreaterThan(3) expect(value).toBeGreaterThanOrEqual(3.5) expect(value).toBeLessThan(5) expect(value).toBeLessThanOrEqual(4.5) // toBe and toEqual are equivalent for numbers expect(value).toBe(4) expect(value).toEqual(4) }) it('adding fl oating point numbers', () => { const value = 0.1 + 0.2 //expect(value).toBe(0.3) This won't work because of rounding error expect(value).toBeCloseTo(0.3) })
  • 134. Babel Coder STRINGS it('there is no I in team', () => { expect('team').not.toMatch(/I/) }) it('but there is a "stop" in Christoph', () => { expect('Christoph').toMatch(/stop/) })
  • 135. Babel Coder ARRAYS const programmingLangs = [ 'JavaScript', 'Python', 'C/C++', 'Java', 'R' ] it('the programming list has R on it', () => { expect(programmingLangs).toContain('R') })
  • 136. Babel Coder EXCEPTIONS function compileAndroidCode() { throw new Con fi gError('you are using the wrong JDK') } it('compiling android goes as expected', () => { expect(compileAndroidCode).toThrow() expect(compileAndroidCode).toThrow(Con fi gError) // You can also use the exact error message or a regexp expect(compileAndroidCode).toThrow('you are using the wrong JDK') expect(compileAndroidCode).toThrow(/JDK/) })
  • 137. Babel Coder MOCK FUNCTIONS function sum(nums, cb) { const result = nums.reduce((result, num) => result + num) cb(result) } describe('sum', () => { it('calls callback correctly', () => { const fn = jest.fn() sum([1, 2, 3], fn) expect(fn.mock.calls.length).toBe(1) expect(fn.mock.calls[0][0]).toBe(6) }) })
  • 138. Babel Coder SETUP AND TEARDOWN beforeAll(() => console.log('1 - beforeAll')) afterAll(() => console.log('1 - afterAll')) beforeEach(() => console.log('1 - beforeEach')) afterEach(() => console.log('1 - afterEach')) it('', () => console.log('1 - test')) describe('Scoped / Nested block', () => { beforeAll(() => console.log('2 - beforeAll')) afterAll(() => console.log('2 - afterAll')) beforeEach(() => console.log('2 - beforeEach')) afterEach(() => console.log('2 - afterEach')) it('', () => console.log('2 - test')) }) // 1 - beforeAll // 1 - beforeEach // 1 - test // 1 - afterEach // 2 - beforeAll // 1 - beforeEach // 2 - beforeEach // 2 - test // 2 - afterEach // 1 - afterEach // 2 - afterAll // 1 - afterAll