본문 바로가기

React

[React] 주요 LifeCycle 함수들 호출 시점 / 활용 방법 / 주의할 점 정리



리액트에서 LifeCycle 개념은 중요하다.
state와 props를 알맞게 관리하고 렌더링을 의도한 대로 다루려면 LifeCycle 개념을 정확히 이해해야 하기 때문이다.
이참에 주요한 몇 가지 LifeCycle 함수들을 살펴보자.


- constructor -

constructor(props) {
    super(props);
    this.state = { date: new Date() };
    this.handleClick = this.handleClick.bind(this);
}


/ 호출 시점
> 생성자 constructor 는 컴포넌트가 마운트되기 전에 호출된다.

/ 활용 목적
constructor 에서는 주로 state를 초기화하거나 이벤트 핸들러 메소드들을 바인딩한다.

/ 주의할 점
> 다른 구문보다도 먼저 super(props)를 실행해야 한다.
그렇지 않으면 this.props 가 정의되지 않아서 버그가 발생할 수 있다.
Uncaught TypeError: Cannot set properties of undefined (setting 'state')
constructor에서는 this.setState() 함수를 실행하지 않고 this.state 에 값을 할당한다.
생성자 함수는 this.state에 값을 직접 할당할 수 있는 유일한 곳이다.
constructor 에서 state를 초기화할 때 props 를 그대로 가져다가 사용하면 안 된다.
props 가 바뀌더라도 state에는 새롭게 반영되지 않기 때문이다.
props를 쓰려면 state 를 거치지 말고 직접 props 에서 꺼내서 
그때 그때  this.props.color 이런 식으로 불러다 써야 한다.

constructor(props) {
    this.state = { color : props.color }; // 안 좋은 예시
}

 

stateprops 값을 넣어서 쓰는 작업은 불필요한 작업이다.
props 가 바뀌었을 때 state 가 바뀌었을 때와 마찬가지로 렌더링이 다시 일어나기 때문이다.
단, props 가 바뀌는 것을 의도적으로 무시하고 쓰고 싶은 경우에는 이러한 방식을 사용할 수도 있다.



- componentDidMount -

componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
    this.initData(this.props.userID);
}


/ 호출 시점
> 컴포넌트가 마운트된 직후, 즉 DOM 트리에 삽입된 직후에 호출된다.

/ 촬용 목적
DOM 노드가 먼저 있어야 하는 초기화 작업은 componentDidMount 에서 하면 된다.
> 외부에서 데이터를 불러와야 한다면 네트워크 요청을 보내기 적절한 시점이다.

/ 주의할 점
> componentDidMount() 에서 setState() 를 호출하는 경우 렌더링이 추가로 발생한다.
하지만 브라우저가 화면을 갱신하기 전에 이루어지기 때문에 사용자는 알아차릴 수 없다.
이렇게 사용하는 방식은 성능 문제를 일으킬 수 있으므로 잘 써야 한다.
하지만 모달이나 툴팁처럼 렌더링하기 전에 먼저 DOM 노드의 크기나 위치를 측정해야 하는 경우 이러한 방식이 필요할 수 있다.
> 대부분의 경우는 componentDidMount() 대신에 constructor() 단계에서 초기 state 를 할당할 수 있다.
props 에 의존하는 state 가 필요할 때는 어떻게 해야 하는지 알고 싶다면 아래 글을 참고하자
https://ko.reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html

 

 


- componentDidUpdate -

componentDidUpdate(prevProps) {
    if(this.props.userID !== prevProps.userID) {
        this.fetchData(this.props.userID);
    }
}


/ 호출 시점
> 갱신이 일어난 직후에 호출된다. 렌더링이 새롭게 일어날 때마다 실행된다고 이해하면 편하다.
> 단 최초 렌더링에서는 호출되지 않는다.

/ 활용 목적
> 컴포넌트가 갱신되었을 때 DOM을 조작하고 싶다면 componentDidUpdate 가 적절한 시점이다.
> 이전 props 와 새로운 props 를 비교하여 네트워크 요청을 보내야 할 때 사용해도 좋다.

/ 주의할 점
props 를 그대로 state 에 넣어서 사용하는 것은 좋지 않다.
되도록이면 state 를 거치지 않고 props 를 직접 사용하는 것이 좋다.
이점은 constructorcomponentDidMount 와 비슷하다.
> componentDidUpdate 는 전달 인자로 이전 props 를 받아온다.
props 를 활용하여 특정한 값이 바뀌는지 감지하도록 조건문으로 감싸야 한다.
조건문이 없다면 렌더링이 무한 반복하여 발생할 수 있다.

/ 고급
> 만약 컴포넌트에서 getSnapshotBeforeUpdate() 를 구현했다면 componentDidUpdate() 의 동작이 조금 달라진다.
getSnapshotBeforeUpdate() 가 return 하는 값은 componentDidUpdate() 에 세 번째 전달인자로 넘어온다. 
또한 getSnapshotBeforeUpdate()falsereturn 한다면 componentDidUpdate 는 실행되지 않는다.
만약 getSnapshotBeforeUpdate() 를 구현하지 않았다면 세 번째 파라미터는 undefined 로 넘어온다.

 

 

 

- componentWillUnmount -

componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
}


/ 호출 시점
> 컴포넌트가 마운트 해제되어 제거되기 직전에 호출된다.

/ 활용 목적
> 타이머 제거, 네트워크 요청 취소, 구독 해지 등 정리해야 하는 작업들이 있다면 componentWillUnmount 가 적절한 시점이다.

/ 주의할 점
> 이제 컴포넌트가 다시 렌더링되는 일 없이 아주 사라지므로 setState() 를 호출하면 안 된다.

 

> 참고
https://ko.reactjs.org/docs/react-component.html


- 221108







반응형