[코드캠프]17일차_TIL_class

윤성해·2023년 4월 3일
0

프론트엔드_TIL

목록 보기
15/27
post-thumbnail

수업 목표

  1. class란?
  2. class 컴포넌트의 생명주기
  3. 함수형 컴포넌트의 생명주기 훅 useEffect
  4. open-api

수업 리뷰 (댓글수정, 무한스크롤)
댓글 무한스크롤 컨테이너랑 프레젠터, ui와 함께 확인


밑에 덩어리들을 컴포넌트로 분리시킨다면, 댓글마다 독립저인 컴포넌트가 될 거다. 만드는 방법은 isEdit, isEdit를 주고 분리가 되었고 아이템이라는 컴포넌트로 관리했다.


디폴트값 해주려고 el 넘겨준다. isEdit 바탕으로 등록하기, 수정하기 창 나오게 할 수 있다. isedit가 false면 등록뮤테이션이 날라가기.
setISEdit는 왜 props로 넘겨주는걸까?

isedit가 있냐 없냐에 따라 모양이 다르다

defaultvaule말고 밸류를 사용해야할 때


수정뮤테이션이!

이건 왜 셋이즈에디트 ??

  • 게시글 등록하기는 입력하고 상세페이지로 이동이 된다. 알아서 입력했던 내용들이 삭제가 되었었다. 댓글같은 경우는 입력하고 등록하기 누르면, 아래쪽에 댓글이 추가가 된다. 원래 등록하기에 있던 내용을 지워주고자

    벨류를 사용했다. 비워진 내용이 바인딩이 되어야하기 때문에. 밸류를 사용하면 디폴트밸류는 못사용한다.

    셋이즈 에디트는 수정하기 눌렀을때 수정하고 false로 바꿔주는애다.
    온클립 업데이트는 이즈에디트를 트루로 만들어준다. 그러면 트루때문에 댓글이 수정컴포넌트로 변경된다. 그러면 수정완료하면 isedit 를 false로 만들어서 다시 상세컴포넌트로 바뀌게된다.
  1. 무한스크롤
  2. 댓글 컴포넌트
  3. 부모컴포넌트에서 내려주는거
  4. 디폴트밸류를 밸류처럼 쓰기
    4가지 복습해주기!

1. class란?

class는 객체이자 물건을 만드는 설명서입니다.
class안에는 함수와 변수를 넣을 수 있습니다. 이 변수와 함수를 조합해 붕어빵과 몬스터를 만드는 방법을 적어둘 수 있습니다. 그리고 붕어빵과 몬스터를 만들고 싶다면 new 붕어빵() 으로 만들어 줍니다.
만들어진 붕어빵과 몬스터는 객체 또는 인스턴스라고 부릅니다.

💡 클래스에서의 함수와 변수 사용법
클래스에서 함수와 변수를 사용할때는 function,let,const를 붙이지 않습니다.

class Monster {
  // class의 변수 작성
  power = 50;

  // class의 함수(메소드) 작성
  attack(): void {
    console.log("공격합니다!!");
  }
}

클래스에서 만들어진 함수메소드라고 부릅니다.

💡클래스에서의 상속 (extends Monster 부분 참고)
클래스에서는 공통 기능을 extends를 통해 상속 해줄 수 있습니다.

class Monster {
  power = 50;
  attack(): void {
    console.log("공격합니다!!");
  }
}

// 클래스 상속 : 기존 클래스에 기능을 추가해서 만든 클래스
class SuperMonster extends Monster {
  run(): void {
    console.log("도망가자!!");
  }

  // 오버라이딩: Monster의 메소드를 다시 정의해서 덮어씌운다.
  attack(): void {
    console.log("슈퍼 몬스터 필살기!!");
  }
}

const monster = new Monster();
console.log(monster.power); // 50
monster.attack(); // 공격합니다!!

const supermonster = new SuperMonster();
console.log(supermonster.power); // 50
supermonster.attack(); // 슈퍼 몬스터 필살기!!

💡 class component 만들어보기 실습

//count 컴포넌트를 만들어보겠습니다.
import {component} from 'react'

export default class ClassCounterPage extends Component {
	// class 변수의 선언 방식
	state = {
				count : 0,
			}

	// class에서의 함수 사용방식 
		onClickCounter = () =>{
				console.log(this.state.conut)
				this.setState(((prev))=>({
						count : this.state.count(=prev.count) +1
			}))
		}

	// 화면 그리는 부분
	render(){
		return(
			<div> 
				{/* this는 class 자기자신을 뜻합니다. */}
					<div>현재 카운트 : {this.state.count}</div>
				{/* 직접 바인딩할 때는 onClick={this.onClickCouter.bind(this)} 라고 적어주셔야 합니다. */}
					<button onClick={this.onClickCouter}>카운트 올리기</button>
			</div>
			)
		}
	}

💡 this 바인딩( .bind(this) )
this는 어디서 실행하냐에 따라서 변화하는 이슈가 있습니다. 즉, 실행하는 주체에 따라서 this가 다르게 나옵니다. 이렇게 바뀌는 this를 동적 this라고 합니다.
따라서 onClickCounter 를 클릭시에 this가 onClickCounter로 바뀌게 됩니다. 변화하는 this를 class로 고정하기 위해서는 this를 바인딩해주시거나 화살표 함수를 써주셔야합니다.
이렇게 바인딩 과정을 거쳐서 고정된 this를 렉시컬 this라고 합니다.

2. class 컴포넌트의 생명주기(Life Cycle)

컴포넌트의 생명주기는 컴포넌트가 브라우저에 나타나고 업데이트 되고, 사라지게 될 때 호출되는 메서드 입니다. 쉽게 말해, 특정 시점에 코드가 실행되도록 설정할 수 있다는 것입니다.
메서드에 대해 간략히 요약한다면,

  1. 그리기 → render 인풋창 그리기
  2. 그리고 난 뒤 → componentDidMount(포커스 깜빡 깜빡 처리는 여기서!)
  3. 그리고 난 뒤 변경됐을 때 → componentDidUpdate
  4. 그리고 난 뒤 사라질 때 → componentWillUnmount
// class 컴포넌트의 생명주기
import {Component} from 'react'
import Router from 'react'


export default class ClassCounterPage  extends Component{
		state = {
					count : 0,
				}


//라이프사이클 메서드
componentDidMout(){
		console.log("마운트 됨")
		//input태그 선택해서 포커스 깜빡거리게 하기
	}
componentDidUpdate(){
		console.log("수정하고 다시 그림!!")
	}
componentWillUnmount(){
		console.log("여기서 나갈래요")
		//나가기 전에 마지막으로 할 것들
	}


// 카운트 올리기 함수
onClickCouter = ()=>{
		console.log(this.state.conut)
		this.setState(((prev))=>({
		count : this.state.count(=prev.count) +1
			}))
	}

// 현재 페이지 나가기 함수 _ componentWillUnmount를 보기위한
onClickMove = () => {
		router.push('/')
	}
// 화면 그리는 부분
render(){
	return(
		<div> 
			// this는 class 자기자신을 뜻합니다.
				<div>현재 카운트 : {this.state.count}</div>
	
			// 직접 바인딩 하실때는 onClick={this.onClickCouter.bind(this)} 라고 적어주셔야 합니다.
				<button onClick={this.onClickCouter}>카운트 올리기</button>
				<button onClick={this.onClickMove}>나가기</button>
		</div>
		)
	}
}

페이지가 그려진 후 componentDidMount를 console.log를 통해 확인할 수 있습니다.
카운트를 올리고 난 후, componentDidUpdate를 통해 수정된 것을 확인할 수 있습니다.
페이지 이동하기를 통해 componentDidUnmount가 실행되는 것을 확인할 수 있습니다.

3. 함수형 컴포넌트의 행명주기 훅useEffect

클래스형 컴포넌트에는 componentDidMout와 같은 생명주기 메서드들이 있습니다. 그렇다면 함수형 컴포넌트에서는 어떻게 사용할까요? 함수형 컴포넌트에는 생명주기관련 훅이 있습니다. 바로 useEffect 입니다.

useEffect

componentDidMount

// 의존성 배열[]에 아무것도 넣지 않으면 Mount시에만 렌더해주고 끝나게 됩니다.(1번만 실행)

useEffect(()=>{
		console.log("마운트 됨!!")
	},[])

componentDidUpdate와 비슷

// 의존성 배열이 없기 때문에 뭐 하나라도 바뀌면 무조건 다시 실행됩니다.
useEffect(()=>{
		console.log("수정하고 다시 그려짐!!")
	})

// someState가 수정될때만 리렌더 해주기
useEffect(()=>{
		console.log("수정하고 다시 그려짐!!")
	},[someState])

componentDidUpdate와 비슷하지만 다른점은, Mount 됐을 때도 한번 실행되는 점입니다.

componentWillUnmount

useEffect(()=>{
		console.log("수정하고 다시 그려짐!!")

		//이부분이 끝나고 진행할 것들
		return(()=>{
			console.log("여기서 나갈래요!!")
		})
	})

💡 만일 까먹고 useEffect에 의존성 배열을 적어주지 않고 return 또한 해주지 않으셨다면, 무한렌더 지옥에 빠지시게 될 것 입니다. 또한, useEffect는 의존성 배열 인자에 따라 렌더가 달라지므로 의존성 배열을 잘다뤄주는게 중요합니다. 즉, 의존성 배열이 함수형 컴포넌트의 생명주기를 결정하는 포인트라고 보셔도 무방합니다.

💡 useEffect의 실행 시점
→ 생명주기 메서드,훅 은 기본적으로 렌더(화면그리기) 이후에 실행됩니다.
따라서 useEffect와 lifecycle 메서드는 렌더 이후에 실행됩니다.

useEffect 사용시 주의 사항

useEffect 안에서 setState의 사용
→useEffecrt 내에서 setState를 사용할때는 정말 필요한 경우가 아니라면 지양하시는게 가장 좋습니다.

컴포넌트가 마운트된 이후에 setState를 적용하게 되면,
1. state가 변경되고,
2. 변경된 state로 컴포넌트가 다시그려지게(=리렌더) 됩니다.

즉, useEffecrt 내에서 setState를 사용하게 되면 불필요한 리렌더나 무한루프를 일으키게 되고 성능면에서 비효율적이게 됩니다.

2. open - api

오픈api란, 누구든지 사영할 수 있도록 공개된 api 를 말합니다.
예를들면 동물이미지, 날씨 정보, 바이러스 정보, 금융 정보 등 여러 정보드를 api를 통해 무료로 데이터사용이 가능합니다. 이런 오픈api를 잘 사용한다면 백엔드 없이도 서비스를 만드는 것이 가능합니다.

다양한 오픈API 사이트 모음
(구글에 public api 를 검색하면 나옴)

Dogs open-api 실습

위의 링크를 클릭해 들어가 여러가지 카테고리 중 animals 를 들어갑니다. animals에 들어가 Dogs를 클릭합니다. 아래 사진 부분의 Fetch!를 이용해 주소를 복사해주세요.

useEffect와 open-api

우선, axios를 사용하기위해 axios를 설치하고 import 해와야 합니다.
useEffect에는 async를 붙일 수 없어, useEffect 안에 함수를 선언하고 함수를 실행하도록 해야 합니다.

import { useEffect, useState } from "react";
import axios from "axios";

export default function RestGetPage(): JSX.Element {
  const [img, setImg] = useState("");

  useEffect(() => {
    // async를 붙이기 위해 함수를 선언하고, 만든 함수를 실행시켜야 합니다.
    const getImg = async (): Promise<void> => {
      const result = await axios.get("https://dog.ceo/api/breeds/image/random");
      setImg(result.data.message);
    };
    void getImg();
  }, []);

  return <img src={img} />;
}

브라우저가 실행되자마자 실행하려면, useEffect를 사용하지않고 그냥 적어줘도 되지않나요?
→ 가능은 합니다. 하지만, 리렌더면에서 비효율적으로 작동됩니다. (계속해서 실행됩니다!)
리렌더의 조건에는 state의 변화가 있습니다. 그렇다면 컴포넌트의 state가 변할때마다 다시 렌더하게 되겠죠?
불필요한 리렌더는 반드시 제거해야 합니다.

오픈 api 볼 때 참고!

auth : 인증. 인증받은사람만 할 수 있다. 무료는 맞지만 로그인을 해야하는 것
HTTPS : 자물쇠가 달린거 , 보안이 강화 되어있는 api 인가? 엑시오스로 요청. rest api 이다 대부분 (https:// ~~~)
CORS : 일단은 yes 라고 적용되어있는 것만 해보자. no는 디테일한 설정이 필요하다!

rest api는 엑시오스지만 밑처럼 리액트쿼리로 사용가능

슬라이도 Q&A


이건 첫 실행, 변경까지 감지 (모든변경 감지)
여기서 아래처럼 쓰면

count만 변경되었을 때 감지된다. 의존성배열에 아무것도 없으면 count가 없으면 그 어떤것도 변경 감지를 하고싶지 않다. 첫1회만 실행하고, 이후는 어떤것도 감지하고싶지 않다. -> componentDidMount 역할을 하는 것.

render() 안에 있는 애가 화면에 그려지는 것.
렌더 함수 안에 jsx를 그려놔야 한다. setState안에서 재실ㅇ행 되는것이렌더함수 재실행임


🤷🏻‍♀️ 궁금한 것


❗️ 알게된 것


✨ 느낀 점

요새는 정말 수업따라가고 과제 제출하는데 급급해서 블로그 작성을 제대로 못하고있다.. 그치만 엄청 느끼는것은 ㅠㅠ 기능구현에 성공한 것이라도 나중에 어떻게했지 생각해보면 까먹었.. 아무래도 정확하게 알고 한게 아니라 이것저것 해보다가 성공한거라 계속 까먹는 것 같다.
꼭 꼭 꼭 간단하게라도 기능구현한것들 정리해놓는 습관을 가지자.(고 싶다.) 제발 !

profile
Slow and steady wins the race.

0개의 댓글