React_Deep_Dive_4_클래스 컴포넌트

조용환·2024년 1월 18일
0

React_Deep_Dive

목록 보기
4/12

클래스 컴포넌트

16.8미만 작성된 코드는 클래스 컴포넌트가 대다수일 것. 클래스 컴포넌트를 만들려면 클래스를 선언하고 extends로 만들고 싶은 컴포넌트를 extends해야한다.
extends 구문에 넣을 수 있는 클래스는

  • React.Component
  • React.PureComponent
    2가지이다. 이 둘은 클래스 컴포넌트인 shouldComponentUpdate를 다루는 데 차이가 있다.

클래스 컴포넌트 예제

import React from 'react'

interface SampleProps {
  required?: boolean
  text: string
}

interface SampleState {
  count: number
  isLimited?: boolean
}

class SampleComponent extends React.Component<SampleProps, SampleState> {
  
  private constructor(props: SampleProps) {
    super(props)
    this.state = {
      count: 0,
      isLimited: false,
    }
  }
  private handleClick = () => {
    const newValue = this.state.count + 1
    this.setState({ count: newValu,e isLimited: newValue >= 10})
  }
  
  public render() {
    
    const {
      props: { required, text},
      state: { count, is Limited },
    } = this
    
    return (
      <h2>
      	Sample Component
      	<div>{required ? '필수' : '필수아님'}</div>
		<div>문자 : {text}</div>
		<div>count: {count}</div>
		<button onClick ={this.handleClick} disabled={isLimited}>
  			증가
		</button>
	  </h2>
	)
  }
}

constructor() :

  • 컴포넌트 초기화 시점에 호출 state 초기화,
  • React.Component의 생성자 함수를 먼저 호출해 필요한 상위 컴포넌트에 접근할 수 있게 도와줌.
  • ECMA2022에 추가된 클래스 필드 덕에 별도 초기화(constructor)없이 state 초기화 가능해짐.

props :

  • 함수에 인수를 넣는 것과 비슷하게, 컴포넌트에 특정 속성 전달 용도

state :

  • 클래스 컴포넌트 내부에서 관리하는 값을 의미
  • 항상 객체여야 함.
  • 값에 변화가 있을 때마다 리렌더링 발생

메서드 :

  • 랜더링 함수 내부에서 사용되는 함수
  • DOM에서 발생하는 이벤트와 함께 사용
  • 만드는 방법은 크게 3가지
    - constructor에서 this 바인딩
    일반적인 함수로 메서드를 만들면 this가 undefined가 됨 생성자가 아닌 일반 함수로 호출하면 this에 전역 객체(strict 모드에서는 undefined가 바인딩 되기 때문. 따라서 bind를 활용해 강제 this 바인딩해야함.
    - 화살표 함수 사용 (실행 시점이 아닌 작성 시점에 this가 상위 스코프로 결정)
    - 렌더링 함수 내부에서 함수를 새롭게 만들어서 전달하는 방법

클래스 컴포넌트의 생명주기 메서드

생명주기는 크게 3가지이다.

  • mount : 컴포넌트가 마운팅(생성)되는 시점
  • update : 이미 생성된 컴포넌트의 내용이 변경(update)되는 시점
  • unmount : 컴포넌트가 더 이상 존재하지 않는 시점

render()

  • 생명주기 메서드 중 하나
  • 리액트 클래스 컴포넌트의 유일한 필수 값으로 항상 쓰임
  • 컴포넌트 UI 렌더링에 쓰임
  • 마운트와 업데이트 과정에서 일어남
  • 항상 순수해야 하며 no side-effects 여야한다. (같은 입력값에 항상 같은 결과)

componentDidMount()

  • 컴포넌트 마운트 이후 준비되는 즉시 실행
  • render()와는 다르게 this.setState()로 state 값 변경 가능
  • UI 업데이트 이전에 렌더링을 다시 하기 때문에 사용자가 변경되는 것을 눈치 못챔
  • setState는 기본적으로 생성자에서 하는 것이 좋음.
  • 생성자 함수에서 할 수 없는 것, API 호출 후 업데이트, DOM에 의존적인 작업(이벤트 리스너 추가 등)에서만 사용 권장

componentDidUpdate()

  • 컴포넌트 업데이트 이후 실행
  • state, props의 변화에 따라 DOM 업데이트
  • this.setState 사용 가능, 허나 무한 루프 발생가능

componentWillUnmount()

  • 언마운트 or 더 이상 사용되지 않기 직전에 호출
  • 클린업 함수 호출하기 위한 최적의 위치
  • this.setState 호출 불가

shouldComponentUpdate()

  • state나 props의 변경으로 리액트 컴포넌트가 리렌더링 되는 것을 막을 때 사용
  • 컴포넌트에 영향 받지 않는 변화 정의 가능
  • 특정 성능 최적화 상황에서만 고려
ex) 
shouldComponentUpdate(nextProps: Props, nextState: State) {
  //false인 경우, 즉 props의 title이나 state의 input이 같은 경우에는 컴포넌트를 업데이트하지 않음.
  return this.props.title !== nextProps.title || this.state.input !== nextState.input
}

static getDerivedStateFromProps()

  • 가장 최근 도입된 생명주기 메서드
  • 리액트 훅으로 구현 x
  • 이전에 있었으나 이제는 사라진 componentWillReceiveProps를 대체할 수 있는 메서드
  • render() 호출 직전 호출
  • static이기에 this로 접근 불가능
  • 여기서 반환하는 객체는 해당 객체의 내용이 모두 state로 들어가게 됨
  • 모든 render() 실행 시 호출 됨

getSnapShotBeforeUpdate()

  • 가장 최근 도입된 생명주기 메서드
  • 리액트 훅으로 구현 x
  • componentWillUpdate()를 대체할 수 있는 메서드
  • DOM 업데이트 직전 호출
  • componentDidUpdate로 전달
  • DOM 렌더링 전 윈도우 크기 조절, 스크롤 위치 조정 등의 작업을 처리하는 데 유용

지금까지의 생명주기 메서드 정리

getDerivedStateFromError()

  • 에러 상황에서 실행되는 메서드
  • 리액트 훅으로 구현 x
  • 에러 처리 로직 구현 가능
  • render 단계에서 실행

componentDidCatch

  • 자식 컴포넌트 에러 발생 시 실행
  • getDerivedStateFromError에서 에러를 잡고 satte 결정 이후 실행
  • 인수 두 개를 받는데 첫 번째는 getDerivedStateFromError와 동일한 error
  • 두 번째는 어떤 컴포넌트가 에러를 발생시켰는지 정보를 가지고 있는 info
  • 커밋 단계에서 실행되며, 부수 효과 수행 가능
  • 개발 모드에서는 window까지 전파, 프로덕션 모드에서는 componentDidCatch로 잡히지 않은 에러만 window까지 전파.

클래스 컴포넌트의 문제점

  • 데이터 흐름 추적이 어렵다.
  • 애플리케이션 내부 로직의 재사용이 어렵다.
  • 기능이 많아질수록 컴포넌트의 크기가 커진다.
  • 클래스는 함수에 비해 상대적으로 어렵다.
  • 코드 크기 최적화가 어렵다.
profile
practice react, javascript

0개의 댓글