React : LifeCycle

wonkeunC·2021년 5월 3일
0

React

목록 보기
2/4
post-thumbnail

Mounting

마운팅 (Mounting)은 태어나는 것과 같다.

Updating

일반적인 업데이트를 의미한다.

UnMounting

언마운팅(UnMounting)은 Component가 죽는걸 의미한다.
1. 페이지를 변경할때 Component가 죽는다고 표현한다.
2. state를 사용해서 Component가 교체될때. 등..

  • (네트워크 요청) fetch() 중점인 LifeCycle 동작 원리
    Mounting : constructor -> render -> componentDidMount -> fetch() -> fetch(응답) ->
    Updating : (fetch 응답) setState() -> render -> componentDidUpdate

render 은 총 2번 실행 된다. 첫 마운팅에 대한 rendering, setState로 인해 값이 변경된 사항에 대하여 rendering.

componentDidMount에 둬야 할 내용을 componentDidUpdate에 넣었을 경우 무한 rendering이 될 수 있다는 점을 주의하자.

constructor 메서드

constructor 메서드의 구조

  • constructor(props)

props 매개변수는 컴포넌트의 기본 속성값이 적용된 상태로 호출된다.
constructor 메서드 내부에서 반드시 super 함수를 호출해야 한다.

class MyComponent extends React.Component {
  constructor(props) {
  super(props);  // super 함수를 호출해야 React.Component 클래스의 constructor 메서드가 호출된다.
                // 따라서 super 함수를 호출하지 않으면 컴포넌트가 제대로 동작하지 않는다.
  }
}

다행히 개발자 모드에서는 super 함수를 호출하지 않는 경우 예외를 발생시킨다.
constructor 메서드 작성이 필요한 대표적인 예는 초기 속성값으로부터 상탯값을 만드는 경우다.

- 초기 속성값으로부터 상태값을 만들기-
class MyComponent extends React.Component {
  constructor(props) {
  super(props);  
  this.state = {
  	movieList: props.age < 10 ? '배트맨' : '수퍼맨',
    };
  }
}

위 코드처럼

this.state = { // 이렇게 상태값을 직접 할당하는 것은 constructor 메서드에서만 허용된다.
              // 다른 생명주기 메서드에서는 상태값을 변경할 때는 setState 메서드를 사용해야 한다.
              
        movieList: props.age < 10 ? '배트맨' : '수퍼맨',  // 초기 속성값을 이용해서 상탯값을 정의하기 위해 
                                                         constructor 메서드를 작성하는 경우가 많다.      
 };

JavaScript 표준이 될 것이 거의 확실한 클래스 필드를 사용하면 constructor 메서드를 사용하지 않고 같은 기능을 구현 할 수 있다.

- constructor 메서드 없이 속성값을 이용하는 코드 -
class MyComponent extends React.Component {
  state = {
    	movieList: props.age < 10 ? '배트맨' : '수퍼맨',
        // movieList 상태값이 초기에만 age 속성값에 의존적이라고 가정한 코드.
  }
}

클래스 필드를 사용하면 constructor 메서드 없이도 초기 속성값으로부터 상태값을 정의할 수 있다. 참고로 클래스 필드 문법은 create-react-app에서도 지원한다.

만약 movieList

- 속성값에 항상 의존적인 상태값을 함수로 대체한 코드 -
class MyComponent extends React.Component {
   getCurrentMovie() {
     const { age } = this.props;
      return age < 10 ? '배트맨' : '어벤져스';
   }
}

render()

  • render 메서드는 컴포넌트를 정의할 때 반드시 작성해야 한다. render 메서드의 반환값은 화면에 보여질 내용을 결정하며, 속성값과 상태값만으로 결정되어야 한다.
  • render 메서드는 부수 효과를 발생시키면 안 된다.
  1. 서버와 통신하기 (x)
  2. 브라우저의 쿠키에 저장하기 (x)

등은 부수 효과이므로 render 메서드 내부에서는 피해야한다.
부수 효과가 필요하다면 다른 생명 주기 메서드에서 하면 된다.

componentDidMount

처음 한번만 불리는 것, 컴포넌트가 화면상에 mount (태어남) 된다.
구체적으로 설명하자면 render 메서드의 첫 번째 반환값이 실제 돔에 반영된 직후 호출된다.

  • componentDidMount 메서드에서 돔 요소에 접근하는 코드
class Box extends React.Component {
  state = {
    boxWidth: 0,
  };
  divRef = React.createRef();  // 돔 요소에 접근하기 위해 createRef 함수를 사용함
  
  componentDidMount() {
    const rect = this.divRef.current.getBoundingClientRect(); 🦑
    this.setState({ boxWidth: rect.width });
  }
  
  redner() {
    const { boxWidth } = this.state;
    const backgroundColor = boxWidth < 400 ? 'red' : 'blue';
   
   return (
    <div 
      ref = { this.divRef }
      style = {{ width: '100%', height: '100px', backgroundColor }}
    >
    box
    </div>
   )
  } 
}

🦑
1.
componentDidMount 메서드가 호출될 때는 React 요소가 DOM 요소로 만들어진 시점이기 때문에 DOM 요소로부터 필요한 정보를 가져올 수 있다. componentDidMount 메서드에서 setState 메서드를 호출하면 다시 렌더링된다.
2.
componentDidMount 메서드는 API 호출을 통해 데이터를 가져올 때 적합하다.
setState 메서드가 Mount 이후에만 동작하기 때문이다.

constructor 메서드가 componentDidMount 메서드 보다 먼저 호출되기 때문에 API 호출 결과를 더 빨리 받아올 수 있다.
보통의 방법으로 무작정 constructor 메서드에서 호출 후 setState 메서드를 호출하면 데이터가 저장되지 않을 수 있다.
하지만 promise를 사용하면 constructor에서 API를 호출할 수 있게 된다.

- constructor 메서드에서 API 요청을 보내는 코드 -
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.dataPromise = requestData(); 🦋
  }
  
  componentDidMount() {
    this.dataPromise
    .then(data => this.setState({ data })); 🐥
  }
}

🦋
requestData 함수는 API 호출을 하고 promise 객체를 반환한다.

🐥
componentDidMount 메서드에서 API 응답값을 컴포넌트 상태값으로 저장한다.
이 방법은 코드가 다소 복잡해지는 단점이 있다. 따라서 응답 속도에 민감한 애플리케이션이 아니라면 componentDidMount 메서드에서 API를 호출하는 것이 좋은 선택이다.


componentDidUpdate()

componentDidUpdate 메서드는 업데이트 단계에서 마지막으로 호출되는 생명 주기 메서드이다.
쉽게 말해, 요청에 의해서 동작하는 메서드이다. (nav바에서 홈 버튼을 누르거나.. )

구조

  • componentDidUpdate( prevProps, prevState, snapshot )

특징

  • componentDidUpdate 메서드는 가상 돔(virtual DOM)이 실제 DOM에 반영된 후 호출된다. 따라서
    componentDidUpdate는 새로 반영된 DOM의 상태값을 가장 빠르게 가져올 수 있는 생명 주기 메서드이다.

state의 값이 한번 변하게 되면은 LifeCycle에 의해서

setState() -> render() -> componentDidUpdate()
순서대로 무조건 동작한다.
setState()를 사용하는 이유는 setState()는 state의 값이 변할 수 있도록 하는데
그렇기 때문에 다시 rendering을 해줘야한다.

  • 정리
    새로운 props 와 새로운 상태가 setState()에 의해서 변경이 되었을때는 항상
    new props / setState() -> render() -> componentDidUpdate()
    의 LifeCycle 순서를 항상 따라간다.

🧩 componentDidUpdate 메서드는 속성값이나 상태값이 변경된 경우 API를 호출하는 용도로 사용되기도 한다.

: 사용자가 변경되면 친구 목록을 가져오는 API 호출하기 with componentDidUpdate()

class UserInfo extends React.Component {
  componentDidUpdata(prevProps) {
    const { user } = this.props;
    
    if(prevProps.user.id != user.id) {  ☘️
       requestFriend(user).then(friends => this.setState({ friends }));
    }
  }
}

☘️
1. componentDidUpdate 메서드는 내부에서는 이전, 이후의 상태값과 속성값을 모두 알 수 있다.
2. componentDidUpdate 메서드는 초기화 단계에서는 호출되지 않는다. 따라서 친구 목록을 가져오는 API는 componentDidUpdate 메서드에서도 호출할 필요가 있다.


componentWillUnmount( )

componentWillUnmount 메서드는 소멸 단계에서 호출되는 유일한 생명 주기 메서드다.
대표적인 동작
1. 타이머를 해제
2. 종료되지 않은 네트워크 요청을 취소
3. 구독 해제

대표적으로, componentDidMount에서 구독기능을 동작시키고 componentWillUnmount에서 구독해제 기능을 동작시킨다.


추가적으로 알아야 할 점 !

React Hooks에서는 componentDidMount( )componentDidUpdate( )가 합쳐져있다.
하지만 componentDidUpdate() 가 따로 필요할 때가 있는데 특정 변수가 변경된 사항을 감지 해낼때 Hooks에서 componentDidUpdate() 를 사용한다.

profile
개발자로 일어서는 일기

0개의 댓글