IT/React

리액트(React) 스터디일지8: 생명주기(life cycle)

라임웨일 2021. 4. 8. 16:08
반응형

 

컴포넌트의 수명은 페이지에서 랜더링되기 전인 준비 과정에서 시작하여 페이지에서 사라질 때 끝납니다.

 

조금 쉽게 이해를 하기 위해서는 생명주기에 사용되는 접두사를 확인하면 조금 이해하기가 쉽습니다.

  • Will 접두사 : 어떤 작업을 동작하기 전
  • Did 접두사 : 어떤 작업을 동작한 후

 

라이프 사이클은 3가지 카테고리(마운트, 업데이트, 언마운트) 구분됩니다. 아래 리액트 생명주기 표를 보시면 조금 더 이해하기 쉬울거 같습니다.

 

리액트 생명주기 도표

 

1.마운트

DOM이 생성되고 웹 브라우저 상에서 나타나는 것을 마운트라고 합니다.

  • constructor()  - 컴포넌트를 새로 만들때만다 호출되는 생성자
  • getDerivedStateFromProps() - props에 있는 값을 state에 넣을 때 사용
  • render() - 우리가 준비한 UI를 랜더링
  • componentDidMount() - 컴포넌트가 웹 브라우저상에 나타난 후 호출하는 매서드

2. 업데이트

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

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

3.  언마운트

컴포넌트가 DOM 상에서 제거될 때에 호출됩니다.

  • componentWillUnmount()

4. 오류 처리

아래 메서드들은 자식 컴포넌트를 렌더링하거나, 자식 컴포넌트가 생명주기 메서드를 호출하거나, 또는 자식 컴포넌트가 생성자 메서드를 호출하는 과정에서 오류가 발생했을 때에 호출됩니다.

  • getDerivedStateFromError()
  • componentDidCatch()

1. render()

render() 메서드는 클래스 컴포넌트에서 반드시 구현돼야하는 유일한 메서드입니다. 이 메서드가 호출되면 this.props와 this.state의 값을 활용하여 아래의 것 중 하나를 반환해야 합니다. render() 함수는 순수해야 합니다. 즉, 컴포넌트의 state를 변경하지 않고, 호출될 때마다 동일한 결과를 반환해야 하며, 브라우저와 직접적으로 상호작용을 하지 않습니다.

브라우저와 상호작용하는 작업이 필요하다면, 해당 작업을 componentDidMount()이나 다른 생명주기 메서드 내에서 수행하세요. render()를 순수하게 유지하여야 컴포넌트의 동작을 이해하기 쉽습니다. shouldComponentUpdate()가 false를 반환하면 render()는 호출되지 않습니다.

2. constructor()

메서드를 바인딩하거나 state를 초기화하는 작업이 없다면, 해당 React 컴포넌트에는 생성자를 구현하지 않아도 됩니다.  React 컴포넌트의 생성자는 해당 컴포넌트가 마운트되기 전에 호출됩니다. React.Component를 상속한 컴포넌트의 생성자를 구현할 때에는 다른 구문에 앞서 super(props)를 호출해야 합니다. 그렇지 않으면 this.props가 생성자 내에서 정의되지 않아 버그로 이어질 수 있습니다

constructor() 내부에서 setState()를 호출하면 안 됩니다. 컴포넌트에 지역 state가 필요하다면 생성자 내에서 this.state에 초기 state 값을 할당하면 됩니다.  생성자는 this.state를 직접 할당할 수 있는 유일한 곳입니다. 그 외의 메서드에서는 this.setState()를 사용해야 합니다

constructor(props) {
    super(props);
    
    // 여기서 this.setState()를 호출하면 안 됩니다!
    this.state = { counter: 0 };
    this.handleClick = this.handleClick.bind(this);
}

또한 state에 props를 복사하면 안 됩니다! 가장 흔히 범하는 실수 중 하나입니다.

constructor(props) {
    super(props);
    // 이렇게 하지 마세요!
    this.state = { color: props.color };
}

3.componentDidMount()

componentDidMount()는 컴포넌트가 마운트된 직후, 즉 트리에 삽입된 직후에 호출됩니다. DOM 노드가 있어야 하는 초기화 작업은 이 메서드에서 이루어지면 됩니다. 외부에서 데이터를 불러와야 한다면, 네트워크 요청을 보내기 적절한 위치입니다.  이 메서드는 데이터 구독을 설정하기 좋은 위치입니다. 데이터를 호출이 이루어졌다면, componentWillUnmount()에서 해제 작업을 반드시 수행하기 바랍니다.

4.componentDidUpdate()

componentDidUpdate(prevProps, prevState, snapshot)

 

componentDidUpdate()는 갱신이 일어난 직후에 호출됩니다. 이 메서드는 최초 렌더링에서는 호출되지 않습니다.

컴포넌트가 갱신되었을 때 DOM을 조작하기 위하여 이 메서드를 활용하면 좋습니다. 또한, 이전과 현재의 props를 비교하여 네트워크 요청을 보내는 작업도 이 메서드에서 이루어지면 됩니다 (가령, props가 변하지 않았다면 네트워크 요청을 보낼 필요가 없습니다).

componentDidUpdate(prevProps) {
  // 전형적인 사용 사례 (props 비교를 잊지 마세요)
  if (this.props.userID !== prevProps.userID) {
    this.fetchData(this.props.userID);
  }
}

컴포넌트에서 getSnapshotBeforeUpdate()를 구현한다면, 해당 메서드가 반환하는 값은 componentDidUpdate()에 세 번째 “snapshot” 인자로 넘겨집니다. 반환값이 없다면 해당 인자는 undefined를 가집니다.

주의할점은 componentDidUpdate()는 shouldComponentUpdate()가 false를 반환하면 호출되지 않습니다.

5.componentWillUnmount()

componentWillUnmount()는 컴포넌트가 마운트 해제되어 제거되기 직전에 호출됩니다. 이 메서드 내에서 타이머 제거, 네트워크 요청 취소, componentDidMount() 내에서 생성된 구독 해제 등 필요한 모든 정리 작업을 수행하세요.

이제 컴포넌트는 다시 렌더링되지 않으므로, componentWillUnmount() 내에서 setState()를 호출하면 안 됩니다. 컴포넌트 인스턴스가 마운트 해제되고 나면, 절대로 다시 마운트되지 않습니다.

 

 

반응형