๐Ÿš TIL 0203

JBยท2022๋…„ 2์›” 3์ผ
0

CodeCamp FE 05

๋ชฉ๋ก ๋ณด๊ธฐ
16/33

โฌ‡๏ธ 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.
profile
๋‘๋น„๋‘๋ฐฅ๋ฐฅ

0๊ฐœ์˜ ๋Œ“๊ธ€