๐ TIL 0203
โฌ๏ธ Main Note
https://docs.google.com/document/d/1BgsyQcoqR936eostufcPoSgw8-xjvj6qyF-NG_yU6T4/edit
๐ฅฝ [Class Component]
Class Components is like a instructions for making objects.
For instance, if I want to make a cake,
class Cake{}
=> recipe for making a cake
new Cake ()
=> new Cake is made
โฌ๏ธ Example for Class Monster
- Basically, the class can be used for common functions and can be extended to another functions by using
extends CLASSNAME {
. - class = ๊ณตํต๊ธฐ๋ฅ / ๊ธฐ๋ฅ ์์ ๊ฐ๋ฅ --> extends ์ฌ์ฉ
โฌ๏ธ Example for Class Date
- date is the object, which is also called as OOP.
- Object Oriented Programming
- OOP is used in backend computer; for example if one is trying to make an quthAPI, there are multiple kinds of methods included. And grouping whole login-related API into auth API is OOP.
โฌ๏ธ Class Component Practice
import {Component} from 'react'
interface IState {
count: number
}
export default class ClassCounterPage extends Component{
state = {
count: 0
//๋ฌด์กฐ๊ฑด ๊ฐ์ฒด๋ก ํ๋ฐฉ์ ๋ง๋ค์ด์ค์ผํจ
//writer: "",
//title: "",
//contents: "" ์ด๋ฐ์์ผ๋ก ๋ง๋ค์ด์ค์ผํจ
}
onClickCounter = () => {
console.log(this.state.count)
// ๊ทธ๋ฅ onClickCounter(){ console.log(this.state.count) } ์ผ๋:
//ํด๋ฆญํ๋ ์๊ฐ ํด๋ฆญ์ผ๋ก ์ฃผ์ฒด๊ฐ ๋ฐ๋๋ฉด์ ์ฌ๊ธฐ์์ THIs๋ window๋ฅผ ๊ฐ๋ฅดํค๊ฒ ๋จ
//๊ณ ๋ก console.log(this.state.count) ๋ ์คํ์ด ๋์ง ์์. ์ฌ๊ธฐ์ ์ด๋ this๋ "๋์ this" ๋ผ๊ณ ๋ถ๋ฆ
//์ด this๋ฅผ ๊ณ ์ ์ํค๋ ๋ฐฉ๋ฒ์: onClickCounter ๋ผ๋ ํจ์๋ฅผ ์คํํ ๋ "bind"๋ฅผ ํด์ค ๋ผ๊ณ ํ๋๊ฒ
//ํน์ ํ์ดํ ํจ์๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ฉด this๊ฐ ์๋์ ์ผ๋ก binding์ด ๋จ
// ์ ์ this๊ฐ ๋จ (์ธ์ด์ ์ธ this๋ก ์๋์ผ๋ก ๋๋๊ฒ) ==> "๋ ์์ปฌ this (์ธ์ด์ ์ธ this)"
console.log("์นด์ดํฐ๋ฅผ ํด๋ฆญํ์
จ์ต๋๋ค")
this.setState((prev: IState) =>({
count: prev.count + 1
}))
//or
// this.setState({
// count: this.state.count + 1
// })
}
render (){
//๊ทธ๋ฆผ๊ทธ๋ฆฌ๋ ํจ์
return (
//์ด ์์ html์
๋ ฅํด์ฃผ๋ฉด ๋จ. ๋ฐ๋์ render์์ return์ด ๋ค์ด๊ฐ์ผํจ
<div>
<div>ํ์ฌ ์นด์ดํธ: {this.state.count}</div>
{/* this.state === ์๊ธฐ ์์ ์ state */}
<button onClick={this.onClickCounter}>์นด์ดํธ ์ฌ๋ฆฌ๊ธฐ</button>
</div>
)
}
}
๐ฉน [Component Life-Cycle]
1 ๊ทธ๋ฆฌ๊ธฐ
=> Render
2 ๊ทธ๋ฆฌ๊ณ ๋ ๋ค
=> componentDidMouont
ex) input์ฐฝ์ ๊ทธ๋ ธ๋๋ฐ ๊ทธ๋ฆฌ๊ณ ๋ ๋ค์ Input์ฐฝ์ cursor๋ฅผ ๊น๋นก๊ฑฐ๋ฆฌ๊ฒ ํ๊ณ ์ถ์
--> ๊ทธ๋ฌ๋ฉด ์ผ๋จ render ๊ทธ๋ฆฌ๊ณ ๋์ ๊ทธ๋ ค์ง component์ ์ปค์๋ฅผ ๊น๋นก๊ฑฐ๋ ค์ผํ๋๊ฑฐ์
3 ๊ทธ๋ฆฌ๊ณ ๋ ๋ค ๋ณ๊ฒฝ๋์๋
=> componentDidUpdate
-๋ง์ด ์ฌ์ฉํ์ง ์์
4 ๊ทธ๋ฆฌ๊ณ ๋ ๋ค ์ฌ๋ผ์ง ๋
=> copmonentWillUnmount
ex) ์ฑํ
์ฌ์ดํธ ๋ฐฉ์์ ์ฃผ๊ณ ๋ฐ๊ณ ๋ง์ ํ๊ณ ์์
--> ์ด๋ ๋ฐฑ์๋ ์ปดํจํฐ์์๋ ๋๊ตฌ๋ ๋๊ตฌ๊ฐ ์ด๋ค ์ฑํ
๋ฐฉ์ ์ ์๋์ด์๋ค๋ ์ฌ์ค์ ์๊ณ ์์
--> ์๋ก๊ณ ์นจ ์ํด๋ ๋ฐ์ดํฐ๊ฐ ๊ณ์๊ณ์ ์
๋ฐ์ดํธ๊ฐ ๋๋ ์ค์ธ๊ฒ
--> ๋๊ฐ ๋๊ตฌ์ ์ฐ๊ฒฐ์ด ๋์ด์๋์ง ์ฒดํฌ๋ฅผ ํ๊ณ ์๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฅํจ
import {Component, createRef} from 'react'
import Router from "next/router"
// Goal: ํ์ด์ง ์ ์ ํ์๋ง์ ๊น๋นก๊น๋นก
interface IState {
count: number
}
export default class ClassLifeCyclePage extends Component{
inputRef = createRef<HTMLInputElement>()
//ํ๊ทธ๋ฅผ ๋ณ์์ ๋ฃ๊ณ ์ด๋ค
//createRef๋ react์์ ๋ถ๋ฌ์์ผํจ ๊ฑฐ๊ธฐ์ ์ ๊ณตํด์ฃผ๋ ๊ธฐ๋ฅ์ด๊ธฐ ๋๋ฌธ์
//์ด ๋ณ์๋ ํ๊ทธ๋ ์ฐ๊ฒฐ์ ์ํฌ ์ ์๋๋ฐ ๋ inputํ๊ทธ๋ฅผ ํ๊ฒ ์
state = {
count: 0
//๋ฌด์กฐ๊ฑด ๊ฐ์ฒด๋ก ํ๋ฐฉ์ ๋ง๋ค์ด์ค์ผํจ
//writer: "",
//title: "",
//contents: "" ์ด๋ฐ์์ผ๋ก ๋ง๋ค์ด์ค์ผํจ
}
componentDidMount(){
//ํจ์์ (){}
console.log("๋ง์ดํธ ๋จ")
//input ํ๊ทธ ์ ํํด์ ํฌ์ปค์ค ๊น๋นก๊ฑฐ๋ฆฌ๊ฒ ํ๊ธฐ
this.inputRef.current?.focus()
//์ด inputRef์ ํ์ฌ ์์น์ focusํด์ค
}
componentDidUpdate(){
//component๊ฐ ๋ค์ ๊ทธ๋ ค์ก์๋
//state๊ฐ ๋ฐ๋๋ฉด component๊ฐ ๋ค์ ๊ทธ๋ ค์ง
//re-render๋๊ณ ๋ ์ดํ์ ์คํ๋จ
console.log("์์ ๋๊ณ ๋ค์ ๊ทธ๋ ค์ง")
}
componentWillUnmount(){
console.log("์ฌ๊ธฐ์ ๋๊ฐ๋์น")
//๋๊ฐ๊ธฐ ์ ์ ๋ง์ง๋ง์ผ๋ก ํ ๊ฒ๋ค ์คํ
//๋ฐฑ์๋ ์ปดํจํฐ์ ์ฑํ
๋ฐฉ ๋๊ฐ์ ์๋ฆฌ๊ธฐ (์ด ์ปดํฌ๋ํธ๊ฐ ์ฑํ
๋ฐฉ์ด๋ผ๊ณ ํ๋ค๋ฉด)
}
onClickCounter = () => {
console.log(this.state.count)
// ๊ทธ๋ฅ onClickCounter(){ console.log(this.state.count) } ์ผ๋:
//ํด๋ฆญํ๋ ์๊ฐ ํด๋ฆญ์ผ๋ก ์ฃผ์ฒด๊ฐ ๋ฐ๋๋ฉด์ ์ฌ๊ธฐ์์ THIs๋ window๋ฅผ ๊ฐ๋ฅดํค๊ฒ ๋จ
//๊ณ ๋ก console.log(this.state.count) ๋ ์คํ์ด ๋์ง ์์. ์ฌ๊ธฐ์ ์ด๋ this๋ "๋์ this" ๋ผ๊ณ ๋ถ๋ฆ
//์ด this๋ฅผ ๊ณ ์ ์ํค๋ ๋ฐฉ๋ฒ์: onClickCounter ๋ผ๋ ํจ์๋ฅผ ์คํํ ๋ "bind"๋ฅผ ํด์ค ๋ผ๊ณ ํ๋๊ฒ
//ํน์ ํ์ดํ ํจ์๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ฉด this๊ฐ ์๋์ ์ผ๋ก binding์ด ๋จ
// ์ ์ this๊ฐ ๋จ (์ธ์ด์ ์ธ this๋ก ์๋์ผ๋ก ๋๋๊ฒ) ==> "๋ ์์ปฌ this (์ธ์ด์ ์ธ this)"
console.log("์นด์ดํฐ๋ฅผ ํด๋ฆญํ์
จ์ต๋๋ค")
this.setState((prev: IState) =>({
count: prev.count + 1
}))
//or
// this.setState({
// count: this.state.count + 1
// })
}
onClickMove =() => {
//useํ ํจ์๋ classํ component์์ ์ฌ์ฉ ๋ถ๊ฐ๋ฅํจ (hook์ด๋ผ์)
Router.push("/")
}
render (){
//๊ทธ๋ฆผ๊ทธ๋ฆฌ๋ ํจ์
return (
//์ด ์์ html์
๋ ฅํด์ฃผ๋ฉด ๋จ. ๋ฐ๋์ render์์ return์ด ๋ค์ด๊ฐ์ผํจ
<div>
<input type="text" ref={this.inputRef}/>
<div>ํ์ฌ ์นด์ดํธ: {this.state.count}</div>
<button onClick={this.onClickCounter}>์นด์ดํธ ์ฌ๋ฆฌ๊ธฐ</button>
<button onClick={this.onClickMove}>๋๊ฐ๊ธฐ</button>
</div>
)
}
}
๐ซ [http vs. Websocket]
๐ http
- request and respond exists
๐ WS
- Data is sent immediately from backend. (No need request from frontend)
- Once the exit button is clicked, the data is sent to backend that "I exited the page".
- component๊ฐ ์ฌ๋ผ์ง๋, ์ฆ ์ฑํ ํ๋ฉด์ด ์ฌ๋ผ์ง๋, backend์ ์๋ฆผ
Q. What if automatecally sending alert to backend by using onClick method that is executed as I quit the page?
- ๋ค๋ฅธ ๋ฉ๋ด ํด๋ฆญํด๋ ๋๊ฐ์ง ์ ์๊ณ ํ์ด์ง๊ฐ ์ฌ๋ผ์ก๋ค๋๊ฑฐ ์์ฒด๋ฅผ ๋ฐฑ์๋์ ์๋ ค์ค์ผํ๋ ๊ฒ
- ์ฑํ component ์์ฒด์ willUnmount๋ฅผ ํด์ค์ ๋๊ฐ๋๊ฒ
๐จ [Class to Functional]
import { useRouter } from 'next/router'
import {useEffect, useRef, useState} from 'react'
export default function FunctionLifeCycleRefPage () {
const inputRef = useRef<HTMLInputElement>(null)
const router = useRouter()
const [count, setCount] = useState(0)
useEffect(()=>{
//copmonentDidMount์ ๋์ผ
//๋ค์ "๋ฐฐ์ด"์ ๋ถ์ฌ์ค ์ ์์
console.log("๋ง์ดํธ ๋จ")
//ํ๋ฒ๋ง ์คํ๋จ
inputRef.current?.focus()
//ํด๋นํ๋ ํ๊ทธ๋ฅผ ์ฐพ์ ์ ์๊ณ ๊ทธ ํ๊ทธ์ ํฌ์ปค์ค๋ฅผ ๋ง์ถ๋๊ฒ
return () => {
//์ด ๋ถ๋ถ์ componentWillunmount์ ๋์ผ
console.log("์ฌ๊ธฐ์ ๋๊ฐ๋์น")
}
}, []) //์์กด์ฑ ๋ฐฐ์ด (dependency array)
useEffect(() => {
//componentDidUpdate์ ๋น์ท (99%๊ฐ๊ณ 1% ๋ค๋ฆ)
//--> refresh ํด๋ ์ต์ด ํ๋ฒ์ ์คํ์ด ๋จ
//๋ญ ํ๋๋ผ๋ ๋ฐ๋๋ฉด ์คํ
console.log("์์ ๋๊ณ ๋ค์ ๊ทธ๋ ค์ง")
// setCount((prev) => prev + 1)
// ๋ฌดํ๋ฃจํ ๋น ์ง DAY16 ๊ฐ์ 3์๊ฐ์ฐจ ํ์ธ
},[count]) //--> count๊ฐ ๋ฐ๋์์๋๋ง ์คํ๋จ ()
const onClickCounter = () => {
console.log(count)
console.log("์นด์ดํฐ๋ฅผ ํด๋ฆญํ์
จ์ต๋๋ค")
setCount((prev) =>(prev + 1))
}
const onClickMove =() => {
//useํ ํจ์๋ classํ component์์ ์ฌ์ฉ ๋ถ๊ฐ๋ฅํจ (hook์ด๋ผ์)
router.push("/")
}
console.log("์ด ์ฝ์์ ์ธ์ ์คํ์ด ๋ ๊น์น")
//componentDidMount
//๊ทธ๋ฆผ๊ทธ๋ฆฌ๋ ํจ์
return (
//์ด ์์ html์
๋ ฅํด์ฃผ๋ฉด ๋จ. ๋ฐ๋์ render์์ return์ด ๋ค์ด๊ฐ์ผํจ
<div>
<input type="text" ref={inputRef}/>
<div>ํ์ฌ ์นด์ดํธ: {count}</div>
<button onClick={onClickCounter}>์นด์ดํธ ์ฌ๋ฆฌ๊ธฐ</button>
<button onClick={onClickMove}>๋๊ฐ๊ธฐ</button>
</div>
)
}
- Dependency Array: The function is executed only when the particular user-assigned array is changed. Up here, count is written for useEffect(componentDidUpdate), so if there is any change in "count", the function is executed.
Author And Source
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐ TIL 0203), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค https://velog.io/@j00b33/TIL-0203์ ์ ๊ท์: ์์์ ์ ๋ณด๊ฐ ์์์ URL์ ํฌํจ๋์ด ์์ผ๋ฉฐ ์ ์๊ถ์ ์์์ ์์ ์ ๋๋ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ ์ธ ๋ฐ๊ฒฌ์ ์ ๋ (Collection and Share based on the CC Protocol.)
์ข์ ์นํ์ด์ง ์ฆ๊ฒจ์ฐพ๊ธฐ
๊ฐ๋ฐ์ ์ฐ์ ์ฌ์ดํธ ์์ง
๊ฐ๋ฐ์๊ฐ ์์์ผ ํ ํ์ ์ฌ์ดํธ 100์ ์ถ์ฒ ์ฐ๋ฆฌ๋ ๋น์ ์ ์ํด 100๊ฐ์ ์์ฃผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์ ํ์ต ์ฌ์ดํธ๋ฅผ ์ ๋ฆฌํ์ต๋๋ค