React Class-Based Component

Minjae Kwon·2021년 2월 19일
0
post-thumbnail

Hooks 도입 이후, 과거 Class 컴포넌트에서만 가능하던 상태 시스템, 라이프사이클 메소드가 Functional 컴포넌트에서도 구현이 가능해졌다. 하지만 많은 레거시 코드들이 Class 컴포넌트로 작성되어 있음을 생각해보면, Class 컴포넌트와 Functional 컴포넌트를 둘 다 이해할 수 있어야 한다.

💡 Class 컴포넌트 장점

  • Easier code organisation: helper method 들이 class 내부에 존재하므로 가독성이 좋음
  • 상태 시스템: Easier to handle user input
  • 라이프사이클 메소드: Easier to do things when the app first starts

💡 페이지 로딩 시, React 타임 라인

아래 functional 컴포넌트로 작성된 코드에서 실행 순서는 다음과 같다.

1) JS 파일이 브라우저에 의해 실행된다.
2) App component 가 생성된다.
3) geolocation service 를 호출한다.
4) App 이 JSX 를 반환하고, HTML로 렌더링된다.
5) (잠시 후) geolocation 정보를 얻는다.

const App = () => {
  window.navigator.geolocation.getCurrentPosition(
    (position) => console.log(position),
    (err) => console.log(err)
  );

  return <div>Hi there</div>;
};

위의 코드를 라이프사이클 메소드를 통해 핸들링해보자.
아래 코드는 Class 컴포넌트로 리팩토링 후 변화된 실행 순서이다.

1) JS 파일이 브라우저에 의해 실행된다.
2) App component 의 인스턴스가 생성되고, 가장 먼저 constructor 함수가 실행된다.
3) State 객체가 생성되고, this.state 에 할당된다.
4) render method 가 실행된다.
5) App 이 JSX 를 반환하고, HTML로 렌더링된다.
6) componentDidMount가 실행되고, geolocation service 를 호출한다.
7) geolocation 정보를 얻은 후, this.setState 를 통해 업데이트된다.
8) render method 가 다시 실행된다.
9) update 된 정보를 담아 JSX가 반환된다.

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = { lat: null };
  }
  
  componentDidMount() {
  	window.navigator.geolocation.getCurrentPosition(
        (position) => this.setState({ lat: position.coords.latitude }),
        (err) => console.log(err)
    	);
  }

  render() {
    return <div>Latitude: {this.state.lat}</div>;
  }
}

💡 라이프사이클 타임라인

  • constructor()
  • render() 스크린에 내용이 나타남
  • componentDidMount() render() 실행 후 한 번 실행됨
  • componentDidUpdate() state 업데이트때마다, render() 재실행후 실행됨
  • componentWillUnmount() 컴포넌트가 화면에서 사라질 때 실행됨

💡 라이프사이클 use case

  • constructor state 초기화 등 one-time setup
  • render 자주 실행되므로, JSX 반환 외에 별도의 작업 (api request 등)은 하지 않는 것이 좋음
  • componentDidMount 초기 데이터 로딩
  • componentDidUpdate 상태값/props 변화에 따른 추가 데이터 로딩
  • componentWillUnmount cleanup 이 필요할 때
  • 이외의 라이프사이클 메소드도 있지만 자주 사용되지 않으므로 필요시 별도로 찾아서 사용

💡 constructor 를 생략해도 될까?

consturctor 를 생략해도 된다. 왜냐하면 babel 이 constructor 를 생성하기 때문에, babel 이 컴파일링한 후에는 결과값이 동일하다. 따라서, 아래의 두 코드 역시 동일하게 작동한다.

// with constructor
class App extends React.Component {
 constructor(props) {
    super(props);
   
    this.state = { message: 'hello world' }; 
  }
  
  render() { 
    return <div>Hello world</div> 
  }
}

// without constructor
class App extends React.Component {
  state = { message: 'hello world' }; 
  
  render() { 
    return <div>Hello world</div> 
  }
}

💡 번외) 컴포넌트 파일 안에서 CSS 파일은 어떻게 로딩될까?

예컨대, SeasonDisplay.js 안에서 아래와 같이 CSS 파일을 import 하면, Webpack 이 하나로 묶어내는 과정에서 CSS 파일을 발견하고 index.html 로 가져다 붙인다.

import './SeasonDisplay.css';
import React from 'react';
profile
Front-end Developer. 자바스크립트 파헤치기에 주력하고 있습니다 🌴

0개의 댓글