[React] 클래스형 컴포넌트와 함수형 컴포넌트

Darlene·2021년 8월 5일
7

React

목록 보기
10/13

📋 클래스형 컴포넌트와 함수형 컴포넌트

리액트 컴포넌트는 클래스형 컴포넌트 또는 함수형 컴포넌트로 작성될 수 있다.
클래스형 컴포넌트상태값을 가질 수 있고, 리액트 컴포넌트의 생명 주기 함수를 작성할 수 있다. 그러나 함수형 컴포넌트는 이 모든 일을 할 수 없다. 이 둘의 차이점은 상태값과 LifeCycle를 가질 수 있느냐 없느냐이다.

리액트 버전 16.8부터 훅(Hook)이 등장하면서 함수형 컴포넌트에서도 상태값과 생명 주기 함수 코드를 작성 할 수 있게 되었다.

📕 함수형 컴포넌트

☑️ JSX를 return문을 사용해서 반환

☑️ state를 사용할 수 없다

☑️ 생명 주기 함수를 작성할 수 없다

import React from 'react';

function Hello({ color, name, isSpecial }) {
  return (
    <div style={{ color }}>
      {isSpecial && <b>*</b>}
      안녕하세요 {name}
    </div>
  );
}

export default Hello;

📕 클래스형 컴포넌트

☑️ class 키워드로 시작

☑️ Component로 상속 받음

☑️ render() 함수를 사용해서 JSX를 반환

☑️ props를 조회할 때 this 키워드 사용

import React, { Component } from 'react';

class Hello extends Component {
  render() {
    const { color, name, isSpecial } = this.props;
    return (
      <div style={{ color }}>
        {isSpecial && <b>*</b>}
        안녕하세요 {name}
      </div>
    );
  }
}

export default Hello;

☑️ defaultProps 설정 시 클래스 내부에 static 키워드와 함께 선언

import React, { Component } from 'react';

class Hello extends Component {
  // defaultProps 설정 방법 1
  static defaultProps = {
    name: '이름없음'
  };
  
  render() {
    // ...
    );
  }

  // defaultProps 설정 방법 2
Hello.defaultProps = {
  name: '이름없음'
};
}

export default Hello;

🔖 커스텀 메서드 만들기

☑️ 클래스의 생성자 메서드 constructor 에서 bind 작업

import React, { Component } from 'react';

class Counter extends Component {
  constructor(props) {
    super(props);
    this.handleIncrease = this.handleIncrease.bind(this);
    this.handleDecrease = this.handleDecrease.bind(this);
  }

  handleIncrease() {
    console.log('increase');
    console.log(this);
  }

  handleDecrease() {
    console.log('decrease');
  }

  render() {
    return (
      <div>
        <h1>0</h1>
        <button onClick={this.handleIncrease}>+1</button>
        <button onClick={this.handleDecrease}>-1</button>
      </div>
    );
  }
}

export default Counter;

🔖 상태 선언하기

☑️ 클래스형 컴포넌트에서 state로 상태를 관리

☑️ state 를 선언 할 때에는 constructor 내부에서 this.state 설정

☑️ 클래스형 컴포넌트의 state 는 무조건 객체형태여야 한다

☑️ render 메서드에서 state 를 조회하려면 this.state 를 조회하면 된다.

import React, { Component } from 'react';

class Counter extends Component {
  state = {
    counter: 0
  };
  handleIncrease = () => {
    this.setState({
      counter: this.state.counter + 1
    });
  };

  handleDecrease = () => {
    this.setState({
      counter: this.state.counter - 1
    });
  };

  render() {
    return (
      <div>
        <h1>{this.state.counter}</h1>
        <button onClick={this.handleIncrease}>+1</button>
        <button onClick={this.handleDecrease}>-1</button>
      </div>
    );
  }
}

export default Counter;

🔖 상태 업데이트 하기

☑️ 상태를 업데이트해야 할 때에는 this.setState 함수를 사용

🔖 LifeCycle Method (생명 주기 메서드)

☑️ 생명 주기 함수를 작성할 수 있다

출처: http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/

LifeCycle Method는 컴포넌트가 브라우저상에 나타나고, 업데이트되고, 사라지게 될 때 호출되는 메서드들이다. 추가적으로 컴포넌트에서 에러가 났을 때 호출되는 메서드도 있다.

생명주기 메서드는 클래스형 컴포넌트에서만 사용 할 수 있다.
컴포넌트 라이프 사이클은 크게 마운트 - 업데이트 - 언마운트로 단계로 나뉜다.

실제 프로덕션에서 아래 여섯가지 위주로 life cycle을 관리한다.

🔘 constructor
🔘 render
🔘 componentDidMount
🔘 shouldComponentUpdate
🔘 componentDidUpdate
🔘 componentWillUnmount

🔍 마운트 단계 (초기화 단계)

마운트 단계(초기화 단계)는 최초에 컴포넌트 객체가 생성될 때 한 번 수행된다. 먼저 마운트될 때 발생하는 생명주기들을 알아보자.

1️⃣ constructor
2️⃣ getDerivedStateFromProps
3️⃣ render
4️⃣ componentDidMount

constructor

constructor(props) {
  super(props);
}

constructor는 컴포넌트의 생성자 메서드, 컴포넌트가 만들어지면 가장 먼저 실행되는 메서드이다. 컴포넌트가 브라우저에 나타나기전 즉, render()전에 호출이되는 라이프 사이클 함수이다.

getDerivedStateFromProps

  static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.color !== prevState.color) {
      return { color: nextProps.color };
    }
    
    return null;
  }

getDerivedStateFromProps 메소드는 속성값을 이용해서 새로운 상태값을 만들때 즉, props로 받아온 것을 state에 넣어주고 싶을 때 사용한다.

이 메소드는 render 메서드가 호출되기 직전에 호출되는 라이프 사이클 함수이다.

다른 생명주기 메서드와는 달리 앞에 static을 필요로 하고, 정적 메서드이기 때문에 함수 내부에서 this 객체에 접근할 수 없다.

render

컴포넌트를 렌더링하는 메서드로 컴포넌트를 정의할 때 반드시 작성해야 한다.

render 메서드에서는 부수 효과를 발생시키면 안 된다. 서버와 통신하기, 브라우저의 쿠키에 저장하기 등은 부수 효과이므로 render 메서드 내부에서는 피해야 한다. 만약 부수 효과가 필요하다면 다른 생명 주기 메서드에서 하면 된다.

componentDidMount

componentDidMount() {
  // 외부 api호출, DOM 에 관련된 작업 등
}

componentDidMount 메서드는 render 메서드의 첫 번째 반환값이 실제 돔에 반영된 직 후 호출된다.

따라서 render 메서드에서 반환한 리액트 요소가 돔에 반영되어야 알 수 있는 값을 얻을 수 있기 때문에 해당 컴포넌트에서 필요로 하는 데이터를 요청하기 위해 axios, fetch등을 이용해 외부 api를 호출하는 작업을 진행한다.

🔍 업데이트 단계

업데이트 단계는 초기화 단계와 소멸 단계 사이에서 반복해서 수행된다. 컴포넌트의 속성값 또는 상태값이 변경되면 업데이트 단계가 수행된다. 이 단계에서 실행되는 생명 주기 메서드의 호출 순서는 아래와 같다.

1️⃣ getDerivedStateFromProps
2️⃣ shouldComponentUpdate
3️⃣ render
4️⃣ getSnapshotBeforeUpdate
5️⃣ componentDidUpdate

getDerivedStateFromProps

컴포넌트의 props나 state가 바뀌었을때도 이 메서드가 호출된다.

shouldComponentUpdate

shouldComponentUpdate(nextProps, nextState) {
  // return false 하면 업데이트를 안함
  return true;
  // 기본값으로는 true를 반환
}

shouldComponentUpdate는 컴포넌트 최적화를 할 때 많이 사용 된다. 이 메서드는 컴포넌트가 리렌더링 할지 말지를 결정하는 메서드이다.

render

컴포넌트를 렌더링하는 메서드이다.

getSnapshotBeforeUpdate

  getSnapshotBeforeUpdate(prevProps, prevState) {
    if (prevProps.color !== this.props.color) {
      return this.myRef.style.color;
    }
    
    return null;
  }

getSnapshotBeforeUpdate 메서드는 렌더링 결과가 실제 돔에 반영되기 직전에 호출된다.
따라서 getSnapshotBeforeUpdate 메서드가 호출되는 시점에 이전 돔 요소의 상태값을 가져오기 좋다.

componentDidUpdate

  componentDidUpdate(prevProps, prevState, snapshot) {
    if (snapshot) {
      console.log("업데이트 되기 직전 색상: ", snapshot);
    }
  }

componentDidUpdate 메서드는 업데이트 단계에서 마지막으로 호출되는 생명 주기 메서드다. 이 메서드는 가상 돔이 실제 돔에 반영된 후 호출된다. 따라서 componentDidUpdate 는 새로 반영된 돔의 상태값을 가장 빠르게 가져올 수 있는 메서드이다.

3번째 파라미터로 getSnapshotBeforeUpdate에서 반환한 값을 조회 할 수 있다.

🔍 언마운트 단계 (소멸 단계)

마지막으로 언마운트 단계에서는 다음 생명 주기 메서드가 호출된다.

1️⃣ componentWillUnmount

componentWillUnmount

 componentWillUnmount() {
      // 이벤트 및 연동된 외부 라이브러리 제거
  }

componentWillUnmount 메서드는 컴포넌트가 화면에서 사라지기 직전에 호출된다.

주로 사전에 해당 컴포넌트에 등록했었던 이벤트 및 연관 외부 라이브러리 호출등을 제거할 수 있다.

참고 : https://taling-react-course.com/intro/lifecycle-api.html

참고 : https://react.vlpt.us/basic/25-lifecycle.html

2개의 댓글

comment-user-thumbnail
2023년 1월 1일

useState 사용하면 함수형 컴포넌트도 값을 가질 수 있지 않나요
이번에 리엑트를 처음 시작했는데 너무 헷갈리네요. ㅠ

답글 달기
comment-user-thumbnail
2024년 1월 20일

These CompTIA CompTIA CySA+ CS0-003 questions and answers not only help you in your preparation but also familiarize you with the CompTIA CySA+ exam situation. By attempting our CS0-003 CompTIA CySA+ practice exam questions, you will also learn time management. The best thing is that most questions in our exam dumps are those questions that can be included in upcoming CS0-003 CompTIA CompTIA CySA+ exam dumps. Get access to our test engine so that you can get more updated exam dumps.
CompTIA CS0-003 November 2023 Release

답글 달기