Life-Cycle

내 할일 잘 하기·2023년 2월 22일
0

React

목록 보기
4/9

각 컴포넌트의 생명주기와 주요 메서드

render()

클래스 컴포넌트에서 반드시 구현되어야 하는 유일한 메서드

  • render()이 호출되면, this.props / this.state의 값을 활용하여 다음 리스트 중 하나를 반환해야 함.
    • React 엘리먼트 : 일반적으로 JSX를 활용하여 생성됨.
    • 배열과 Fragment : render 를 통하여, 여러 개의 엘리먼트를 반환함.
    • Portal : 별도의 DOM 하위 트리에 자식 엘리먼트를 렌더링함.
    • 문자열 / 숫자 : DOM 상에 텍스트 노드로서 렌더링됨
    • Boolean / null / undefined : 아무것도 렌더링하지 않음. (대부분의 경우 return test && 패턴을 지원하는 데에 사용되며, 여기서 test는 boolean 값임.)
  • render() 함수는 순수해야한다. 컴포넌트의 state를 변경하지 않고, 호출될 떄마다 동일한 결과를 반환해야 한다. 또한, 브라우저와 직접적으로 상호작용을 하지 않는다. 만약, 브라우저와 상호작용하는 작업이 필요한 경우에는 componentDidMoint() 혹은 다른 생명주기 메서드에서 수행해야 한다.
    render()를 순수하게 유지해야 컴포넌트의 동작을 이해하기가 쉬워진다.

constructor(props)

state 초기화 및 메서드 바인딩

  • 해당 컴포넌트가 마운트되기 전에 호출됨.
  • React.Component를 상속한 컴포넌트의 생성자를 구현할 때에는, super(props)를 가장 먼저 호출해야 하며, 그걸 안하면 this.props가 생성자 내에서 정의되지 않아서 버그가 발생할 수 있음.
  • constructor() 내부에서는, setState()를 호출하면 절대 안됨.
  • 컴포넌트 내에 지역 state가 필요하다면, 생성자 내에서 this.state에 초기 state 값을 할당하면 됨.
constructor(props) {
  super(props);
  // 여기서 this.setState()를 호출하면 안 됩니다!
  this.state = { counter: 0 };
  this.handleClick = this.handleClick.bind(this);
}
  • 생성자는, this.state를 직접 할당할 수 있는 유일한 공간이며, 그 외의 메서드에서는 this.setState()를 사용해야 함.
  • 생성자 내부에서는, 사이드이펙트를 발생시키거나 구독을 수행하면 안됨.
    - componentDidMount() 에서 할 것.
  • state에 props를 복사하면 안 됨 !!!
constructor(props) {
 super(props);
 // 이렇게 하지 마세요!
 this.state = { color: props.color };
}

이것은 불필요한 작업이며(this.props.color를 직접 사용하면 됩니다), 버그를 발생시킵니다(color props의 값이 변하더라도 state에 반영되지 않습니다).

props의 갱신을 의도적으로 무시해야 할 때만 이와 같은 패턴을 사용하기 바랍니다.
이 경우, 해당 props의 이름을 initialColor 또는 defaultColor 등으로 변경하는 편이 자연스럽습니다. 그러면 이후 필요에 따라 컴포넌트가 key를 변경하여 초기 state를 “재설정”하도록 강제할 수 있습니다.

componentDidMount()

컴포넌트가 마운트된 직후, 호출되는 메서드

  • 컴포넌트가 마운트, 즉 트리에 삽입된 직후에 호출된다.
  • DOM 노드가 있어야 하는 초기화 작업은, 해당 메서드에서 수행하면 안 된다.
  • 외부에서 데이터를 불러야와 한다면 네트워크 요청을 불러내기 적절한 메서드이다.
  • 데이터 구독을 설정하기 좋은 위치이다.
  • 데이터 구독이 이루어졌다면, componentWillUnmount() 에서 반드시 구독 해제를 수행하도록 하자.
  • 해당 메서드에서, 즉시 setState()를 호출하는 경우도 있는데, 이로 인하여 추가적인 렌더링은 발생한다. 하지만, 브라우저가 화면을 갱신하기 전에 이루어 질 것이고 이 경우, render()가 두 번 호출되지만 User는 그 중간 과정을 볼 수 없을 것이다.
    이와 같은 사용 방식은 성능의 문제를 야기시키기 좋으므로 주의가 필요하다.
    대부분의 경우에는, constructor() 메서드를 통해 초기 state를 할당하지만 Modal 혹은 Tooltip과 같이, 렌더링에 앞서 DOM 노드의 크기나 위치를 먼처 측정해야 하는 경우에는 이러한 방식이 필요할 수가 있다.

componentDidUpdate(prevProps, prevState, snapshot)

갱신이 일어난 직후에 호출되는 메서드

  • 해당 메서드는 최초 렌더링에는 호출되지 않는다.
  • 컴포넌트가 갱신되었을 떄, DOM을 조작하기 위하여 호출하는 용도로 사용하기 좋은 메서드이다.
  • 외부에서 데이터를 불러야와 한다면 네트워크 요청을 불러내기 좋은 위치이다.
  • 이전과 현재의 props를 비교하여 네트워크 요청을 보내는 작업을 하기 좋은 위치이다.
componentDidUpdate(prevProps) {
  // 전형적인 사용 사례 (props 비교를 잊지 마세요)
  if (this.props.userID !== prevProps.userID) {
    this.fetchData(this.props.userID);
  }
}
  • componentDidUpdate()에서 setState()를 즉시 호출할 수도 있지만, 위의 예시처럼 조건문 등으로 처리해두지 않으면 무한 반복이 발생할 수 있다는 점에 주의하자.
    또한 추가적인 렌더링을 유발하여, 비록 User는 눈치채지 못할지라도 컴포넌트 성능에 영향을 미칠 수 있다.
    상위에서 내려온 prop을 그대로 state에 저장하는 것은 좋지 않으며, prop을 직접 사용하는 것이 좋다. (props -> state로 copy시, 버그 유발 가능)
  • shouldComponentUpdate()가 false를 반환하면 componentDidUpdate()는 호출되지 않는다.

componentWillUnmount()

컴포넌트가 마운트 해제되어, 제거되기 직전에 호출되는 메서드

  • 타이머 제거, 네트워크 요청 캔슬, 구독 해제 등 모든 정리작업을 수행하기 좋은 위치이다.
  • 해당 메서드 이후에, 컴포넌트는 다시 렌더링되지 않으므로 해당 메서드 내에서 setState()를 호출하지 말자.
  • 컴포넌트 인스턴스가 마운트 해제되고 난 후에는, 절대로 다시 마운트되지 않는다..
  • Functional Component → hook을 이용해서 대부분 구현 가능하다.

마운트

컴포넌트의 인스턴스가 생성되어, DOM 상에 삽입될 때에 순서대로 호출되는 메서드들.

  • constructor()
  • static getDerivedStateFromProps()
  • render()
  • componentDidMount()

업데이트

props 또는 state가 변경되면 갱신이 발생하는 메서드들.
컴포넌트가 다시 렌더링될 때 순서대로 호출된다.

  • static getDerivedStateFromProps()
  • shouldComponentUpdate()
  • render()
  • getSnapshotBeforeUpdate()
  • componentDidUpdate()

마운트 해제

컴포넌트가 DOM 상에서 제거될 때 호출되는 메서드.

  • componentWillUnmount()

오류처리

자식 컴포넌트를 렌더링하거나, 자식 컴포넌가 생명주기 메서드를 호출하거나, 자식 컴포넌트가 생성자 메서드를 호출하는 과정에서, 오류가 발생하는 경우에만 호출되는 메서드들.

  • static getDerivedStateFromError()
  • componentDidCatch()
profile
함께 일하고싶은 개발자로 기억될래요

0개의 댓글