이번시간에는 기존의 function 함수를 써왔던 것을 class형 컴포넌트로 변환해서 사용하는 방법을 배웠다.
커리큘럼
- 클래스 컴포넌트?? 그런데 클래스가 무슨 뜻이야?? => Class-Component
- 프론트엔드와 백엔드에 전체 숲을 구경해보자 => Architecture
- 백엔드 API 만들기 체험 => Apollo-Server / graphql
- 이미지 업로드하기 => Cloud-Storage
- 검색하는 버튼없어도 검색이 가능하다! => Debouncing / Throttling
오늘 배운 내용
- 클래스 컴포넌트?? 그런데 클래스가 무슨 뜻이야?? => Class-Component
- this란 무엇이고 왜 자꾸 말썽을 부리는 것인가 => this
- 컴포넌트가 살아숨셔 / 생명주기 => Component-LifeCycle
- API를 무료로 제공하고 있어요 => Open API / public API
클래스란?
클래스란 일종의 물건을 만드는 설명서라고 할 수 있다.
class 붕어빵 {
// 만드는 방법
}
new 붕어빵() // 객체 인스턴스
예를들어 class를 이용해 붕어빵이라는 것을 만들면 그안에는 만드는 방법을 선언해주고 new변수를 사용해
붕어빵이라는 객체 인스턴스를 생성할 수 있다.
class 몬스터 {
// 만드는 방법
hp = 1000
power = 10
attack() {
}
}
new 몬스터()
만드는 방법은 간단한데 몬스터 라는 class에 hp 와 power를 할당해주고 new변수를 사용해 몬스터라는 객체를 만들어 주면 되는 간단한 코드이다.
class Date {
// 만드는 방법
}
// date를 객체라고 불림
// 객체를 만든적은 없음
// 애초에 들어있었음
// Date는 내장객체
const date = new Date()
날짜와 시간을 알려주는 Date변수도 동일하게 class를 선언해준뒤 date에 class로 선언한 Date를 할당해주면 된다.
이떄 date부분을 객체라고 부른다. 객체 자체는 만드는 것이 아닌 애초에 선언한 순간부턴 들어가 있다.
Date는 내장 객체이다
// 함수 메소드
new Date()// 객체
// 객체(객체지향프로그래밍-OOP)
// backend
// authAPI == OOP 객체지향 프로그래밍
// auth.login()
// auth.logout()
// class 형 컴포넌트
class 컴포넌트 {
onChangeMyWriter() {
// 작성자 인풋 변경
}
}
input이 입력될때마다 바뀌는 onChange변수도 class에 선언해줄 수 있다.
컴포넌트에 생명주기
컴포넌트에 생명주기 순서도는 아래와 같다
- 컴포넌트를 처음으로 그려줌 => render
- 컴포넌트를 그리고 난뒤 실행 => componentDidMount
- 그리고 난 뒤에 변경이된다면 => componentDidUpdate
- 그리고 난 뒤에 사라질 경우 => componentDidUnMount
채팅방을 예로 백엔드 컴퓨터에서는 채팅방에 접속한 사람이 누구인지 알고 있고 새로고침을 하지 않아도 자동으로
업데이트가 이루어진다.
자동으로 업데이트 되는 이유는 백엔드 컴퓨터에서는 현재 누가 접속해있는지 체킹하고 있기 떄문이다.
프로늩엔드는 api를 백엔드 서버에 요청하기위한 HTTP를 요청하는데
이런 방식의 통신을 webSokect(웹 소켓)이라 하고 웹 소켓에 연결하면 백엔드에서 정보를 줄 수 있다.
프론트엔드가 요청을 하지 않아도 백엔드에서 자동으로 업데이트를 이뤄주는 방식
중요한 것은 만약 사용자가 채팅방에 나가면 나갔다는 알림을 백엔드 서버에게 줘야하는데
그래야 백엔드가 유저에 대해 관리하는 것이 가능하다.
그리고 난뒤 컴포넌트가 사라질때 알려주는 것을, componentWillUnMount에서 백엔드에게 알려준다.
채팅 화면이 사라질때 백엔드에게 알려주는 것이다. onClick을 이용해서 백엔드에게 알려주는 것도 가능하나
만약 메뉴가 여러개일때 서로 다른 메뉴를 클릭해서 나가는 경우가 있고 또는 모든 버튼이나 어떤 버튼을 클릭해도
페이지가 사라지고 사라진 사항을 백엔드에게 알려줘야하는데, 그렇다고 모든 버튼에 채팅방을 나가는
기능을 만들 수는 있으나 굉장히 비효율적인 방식이다.
그래서 채팅 컴포넌트 자체에다가 unMount를 주면된다.
import { Component } from 'react';
export default class ClassCounterPage extends Component {
state = {
count: 20,
};
class 컴포넌트를 사용하는 방법은 기존의 함수형 컴포넌트와 동일하게 react에서 Component를 불러주면 된다.
클래스형 컴포넌트에서는 함수형과 다르게 useState를 사용하기 위해서는 state라는 변수를 선언하고 그안에
state를 명시한뒤 초기값을 넣어주면 된다.
interface IState {
count: number;
}
onClickCounter = () => {
console.log(this.state.count);
this.setState((prev: IState) => ({
count: prev.count + 1,
}));
console.log(`counter 를 클릭하셨습니다`);
};
기존의 함수형에서 클릭시 count가 추가되는 기능을 만들때는 const를 붙여주었는데 class형에서는
onClick 기능만 넣고 화살표 함수로 감까주면 된다.
그리고 기존의 typescript와 동일하게 type을 주고 onClick안에서 this를 붙여서 setState에 prev 변수를 이용해
클릭시 count를 추가하는 기능을 만들어주면 된다.
{/* this자체를 bind해줘야 실행될때마다 동적으로 바뀌지 않는다. */}
{/* <button onClick={this.onClickCounter.bind(this)}>카운트 올리기</button> */}
<button onClick={this.onClickCounter}>카운트 올리기</button>
그리고 onClick에 추가해주기 위해서는 this를 붙여 onClickCounter를 넣어주면 완성
LifeCycle 생명주기
// 채팅구현시 어떤 버튼을 클릭할지 아무도 모른다.
componentDidMount() {
console.log('마운트 됨!!!');
// input 태그 선택ㄹ해서 포커스 깜빡 거리게 하기
// 이것은 render 이후 두번 다시 실행 안됨
}
componentDidUpdate() {
// 다시 바뀔때
// 다시그려질때 rerender
console.log('수정되고 다시 그려짐!!!');
}
componentWillUnmount() {
console.log('여기서 나갈래!!!!!!!');
// 나가기전에 마지막으로 할것들!!! (백엔드 컴ㅍ터에 채팅방 나감을 알려주는 것)
}
채팅을 구현할때 내가 어떤 버튼을 클릭할지는 아무도 모른다.
그러기 위해서는 3가지의 생명 주기가 있는데
- render => 그리기
- componentDidMount() => 컴포넌트가 그려지고 난뒤에 실행
- componentDidUpdate() => 컴포넌트가 그려지고 난뒤 변경될때
- componentDidUnmount() => 컴포넌트가 그려지고 난뒤 사라질때
이 네가지를 간단히 설명한 것인데 처음에는 render가 그려지고 Mount를 이용해 마운트가 된것을 확인한다.
이것은 render이후에는 두번 다시 실행되지 않는다.
그다음 DidUpdate가 이루어지고 이것은 그려지고 난뒤 변경된다면 실행된다. 다시 그려지면 리렌더링 되는 방식
그리고 그려지난뒤 나가기전 마지막으로 할것을 WillUnmount를 통해 백엔드에게 채팅방에 나감을 알려준다.
처음에는 componentDidMount가 실행되고 그다음 카운터를 올렸을때 ComponentDidUpdate가 실행된다.
최종적으로 나가기 버튼을 누르면 componentWillUnmount가 실행된다.
함수형 컴포넌트와 차이점
함수형 컴포넌트에서는 위처럼 복잡하게 세가지로 나눌 필요 없이 오직 useEffect하나로만 제어가 가능하다.
// 이변수는 태그와 연결할 수 있다
const router = useRouter();
// inputRef = createRef<HTMLInputElement>();
// 함수에서는 초기값도 null 넣어줘야함
const inputRef = useRef<HTMLInputElement>(null);
const [count, setCount] = useState(0);
먼저 class형에서 inputRef를 선언한것과 동일한 코드지만 함수형에서는 초기값에 null을 넣어줘야한다.
useEffect(() => {
console.log('마운트됨!!');
// 해당 하는 current 함수를 찾고 focus를 맟줄 수 있다.
inputRef.current?.focus();
// useEffect()에서도 setState사용가능
// 좋은 방법은 아님
// state를 바꿔버리니까 바뀐 state로 리렌더 되면서 실행하고 난뒤에
// 계속해서 찍히기 떄문에 별로 좋은 방법은 아니다.
// setCount(prev => prev + 1);
// []를 의존성 배열 = defenderrcy array
// 컴포넌트가 리렌더 되면 다시 실행되나
// 배열에 있는 count가 바뀔때만 실행이된다.
// 셋중에 하나만 바뀌면 useEffect 실행한다.
// 배열이 없다면 아무가너 하나라도 바뀌면 실행
// componentDidUpdate와 비슷하다.
// 빈배열이면 한번만 실행하고 바뀜
// return 부분이 만들어지고 useEffect가 실행됨
// componentWillUnMount 와 동일
// 종료될때 실행
return () => {
console.log('여기서 나감');
};
}, []);
useEffect를 사용하는 방법은 간단하다.
useEffect안에 input이 focus되는 기능을 적고 return을 이용해 console.log를 넣어 종료될때 실행해주면 된다.
return 부분은 class형에서 componentWillUnMount와 동일하다.
그리고 끝에 [] 배열은 의존성 배열이라고 하는데 만약 이 배열에 count를 넣으면 컴포넌트가 리렌더가 될때
다시 실행되나 배열에 있는 count가 바뀔때만 실행이 된다.
const [count, setCount] = useState(0);
const [title, setCount] = useState(0);
const [contents, setCount] = useState(0);
useEffect(() => {
console.log('마운트됨!!');
return () => {
console.log('여기서 나감');
};
}, [count, title, contents]);
만약 배열안에 넣을 state 3개를 선언하고 useEffect 배열안에 넣는다면 셋중에 하나만 바뀌면 useEffec가 실행된다.
만약 배열안에 아무것도 없을때는 빈배열로 판단하고 한번만 실행한다.
'etc. > TIL' 카테고리의 다른 글
[TIL] 2022년 02월 04일 (0) | 2022.02.04 |
---|---|
[TIL] 2022년 01월 26일 TIL - LAYOUT (0) | 2022.01.26 |
[TIL] 2022년 01월-25일 TIL - Ant Disgin Modal, Husky (0) | 2022.01.25 |