React component의 생명주기

Gisele·2021년 3월 20일
1

리액트 컴포넌트는 생명 주기가 있다. 컴포넌트가 실행되거나 업데이트되거나 제거될 때, 특정한 이벤트들이 발생한다.

class형 컴포넌트

컴포넌트가 생성, 업데이트, 소멸되는 사이클.

import React from 'react';

class LifecycleEx extends React.Component {
  // 생성자 함수
  constructor(props) {
    super(props);

    this.state = {
      cat_name: '나비'
    };

    console.log('in constructor!');
  }

  changeCatName = () => {    
    this.setState({ cat_name: '바둑이' });
    console.log('고양이 이름을 바꾼다!');
  };

  componentDidMount() {
    console.log('in componentDidMount!');
  }

  componentDidUpdate(prevProps, prevState) {
    console.log(prevProps, prevState);
    console.log('in componentDidUpdate!');
  }

  componentWillUnmount() {
    console.log('in componentWillUnmount!');
  }
  
  render() {
    console.log('in render!');

    return (
      <div>   
        <h1>제 고양이 이름은 {this.state.cat_name}입니다.</h1>
        <button onClick={this.changeCatName}>고양이 이름 바꾸기</button>
      </div>
    );
  }
}

export default LifecycleEx;

생성

처음 컴포넌트의 인스턴스가 생성되어 DOM 상에 삽입될 때에 아래 순서대로 호출된다

constructor

  • 컴포넌트가 브라우저에 나타나기전 컴포넌트가 만들어지면 가장 먼저 실행되는 메서드
  • context, defaultProps와 state를 초기화하고, 메서드를 바인딩

render

  • 컴포넌트를 DOM에 부착 = 화면을 그리는 것 = mount

componentDidMount

  • Mount가 완료된 후 호출
  • DOM에 접근할 수 있게됨!
  • ajax 요청이나 setTimeout, setInterval 처리

업데이트

  • state나 props가 바뀔 때나 부모 컴포넌트가 변경됐을 때 업데이트 된다

componentDidUpdate

  • 리렌더링이 끝나고, 화면에 변화가 반영된 뒤에 호출되는 메서드.
  • 파라미터로 prevProps, prevState을 가지고 있어, 이전 상태와 비교할 때 사용할 수 있다.

제거

unmount는 컴포넌트가 화면에서 사라지는 것을 의미한다.

componentWillUnmount

  • 컴포넌트가 화면에서 사라지기 직전에 호출된다.
  • DOM에 직접 등록했었던 이벤트를 제거하고, setTimeout을 했다면 clearTimeout을 해준다.

함수형 컴포넌트

  • 함수형 컴포넌트에서는 useEffect가 라이크사이클을 대체한다.
  • class 컴포넌트는 라이프사이클이 컴포넌트에 중심이 맞춰져 있지만, 함수형 컴포넌트는 특정 데이터에 대해서 라이프사이클이 진행된다.
  • Hook을 이용하면 생명주기 메서드에 따라서가 아니라 코드가 무엇을 하는지에 따라 나눌 수가 있다.
  • 리액트 앱의 흔한 버그 중 하나가 compoenentDidUpdate를 제대로 다루지 않는 것이다. useEffect는 기본적으로 업데이트를 다루기 때문에 업데이트를 위한 특별한 코드가 필요없다.

useEffect

리액트의 class 생명주기 메서드에 친숙하다면, useEffect Hook을 componentDidMountcomponentDidUpdate,componentWillUnmount가 합쳐진 것으로 생각해도 좋습니다

useEffect가 하는 일

렌더링 이후 수행해야 할 일. 리액트는 우리가 넘긴 함수를 기억했다가(=effect) DOM 업데이트를 수행한 이후에 불러낸다.

useEffect를 컴포넌트 안에서 불러내는 이유

함수범위 안에 존재하기 때문에 effect를 통해 state,props에 접근할 수 있다.

useEffect는 렌더링 이후에 매번 수행되나?

기본적으로 첫번재 렌더링과 이후의 모든 업데이트에서 수행된다. 마운팅과 업데이트라는 방식으로 생각하는 대신 effect를 렌더링 이후에 발생하는 것으로 생각하는 것이 더 쉬울 것이다. 리액트는 effect가 수행되는 시점에 이미 DOM이 업데이트되었음을 보장한다.

effect에서 함수를 반환하는 이유

effect를 위한 clean up 메커니즘이다. 모든 effect는 정리를 위한 함수를 반환할 수 있다. effect가 함수를 반환하면 리액트는 그 함수를 정리가 필요한 때에 실행시킨다.

// 클래스형
  componentDidMount() {
    ChatAPI.subscribeToFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }
  componentWillUnmount() {
    ChatAPI.unsubscribeFromFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }
// 함수형
  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    // effect 이후에 어떻게 정리(clean-up)할 것인지 표시합니다.
    return function cleanup() {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

Effect 건너뛰기

  • effect를 건너뛰어 성능 최적화를 원한다면 useEffect의 두 번째 인수로 배열을 넘기면 된다.
  • 배열 인수가 업데이트된 뒤에 렌더링하면 리액트는 이전에 렌더링된 값을 그다음 렌더링 시의 값과 비교하고, 이 때 두 값이 다르면 리액트는 useEffect를 재실행한다.
useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count]); // count가 바뀔 때만 effect를 재실행합니다.

📑 reference

profile
한약은 거들뿐

0개의 댓글