[20220810_React Lifecycle Methods]

YunTrollpark·2022년 8월 10일
1

React

목록 보기
11/12

React Lifecycle Methods

1. React

• React는 component는 상위 component에서 받은 props 를 input으로 하고 React를 구성하는 가장 작은 단위인 Element 를 output으로 하는 함수이다.

2. React Lifecycle

• React에는 Lifecycle이 있다.(React는 생명주기를 가지고 있음)
• 생성자를 통하여 필요한 메모리를 할당하고, 객체의 역할이 끝나면 소멸자를 통하여 메모리를 반환.
→ 컴퓨터의 자원은 한정적이라 역할이 끝나면 모든 메모리를 반환해야 메모리 누수에 문제가 생기지 않고, 더 좋은 성능 발휘 가능

리액트는 컴포넌트 기반의 View를 중심으로 한 라이브러리이다. 그러다보니 각각의 컴포넌트에는 라이프사이클 즉, 컴포넌트의 수명 주기가 존재한다. 컴포넌트의 수명은 보통 페이지에서 렌더링되기 전인 준비 과정에서 시작하여 페이지에서 사라질 때 끝이난다.


: Lifecycle은 보기와 같이 총 9개가 존재함.

출처: http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/

1) Lifecycle의 분류

Each component in React has a lifecycle which you can monitor and manipulate during its three main phases.
리액트에서 각각의 컴포넌트는 3개의 주된 단계에서 모니터하고 조정할 수 있는 Lifecycle이 있다.

The three phases are: Mounting, Updating, and Unmounting.
3개의 단계: 마운팅, 업데이팅, 언마운팅

• React를 사용하면 각 component 단위로 UI를 화면에 보이게 하거나 다른 UI로 변경하고, 현재 보이는 UI를 화면에서 제거 할 수 있다.

• 따라서 각각의 Component들은 생성(Mounting) -> 업데이트(Updating) -> 제거(Unmounting) 단계를 차례로 겪는 생명주기(Life Cycle)를 가지고 있다.

• 리액트는 웹에서 UI데이터가 변경되면 자동으로 컴포넌트가 업데이트되며 동적으로 화면을 그림.

→ 제대로 된 기능을 수행하려면 이런 자동으로 업데이트되는 과정에 끼어들어 API를 호출하기도 하고 데이터를 가공하기도 해야함. 따라서, 생명주기의 각 단계별로 필요한 순간에 필요한 작업들을 끼워넣을 수 있는 메서드들이 존재한다.

1️⃣ Mount(생성)

: DOM이 생성되고 웹브라우저에 나타나는 것
(component가 새롭게 생성되는 시점, component 함수가 실행 → 가상 DOM에 삽입 → 실제 DOM 업데이트)

Methods

1. constructor(생성자)
: 클래스의 인스턴스 객체를 생성하고 초기화하는 특별한 메서드

• React 컴포넌트의 constructor는 해당 컴포넌트가 생성시 호출
• React.Component를 상속한 컴포넌트의 생성자를 구현할 때에는 다른 구문에 앞서 super(props)를 호출
→ 그렇지 않으면 this.props가 생성자 내에서 정의되지 않아 버그로 이어질수도!
• this.props, this.state에 접근이 가능하고 리액트 요소를 반환!

❗️주의사항
: 메서드를 바인딩하거나 state를 초기화하는 작업이 없다면, 해당 React 컴포넌트에는 cunstructor를 구현하지 않아도 됩니다.

// constructor 기본 구조
class MyComponent() extends React.Component{
  constructor(props){
    super(props)
    //...
  }
}
// super 함수를 호출해야 React.Component class의 method가 호출 됨.
// super를 호출하지 않으면? 컴포넌트 작동 ❌

2. static getDerivedStateFromProps()

•props로부터 파생된 state를 가져옵니다. 즉 props로 받아온 것을 state에 넣어주고 싶을때 사용
• 해당 API 는 props 로 받아온 값을 state 로 동기화 하는 작업을 해줘야 하는 경우에 사용.

❗️주의사항:
• 정적 메서드기 때문에 this를 호출할 수 없음.
• 이 메서드는 이유와 상관없이 렌더링 때마다 매번 실행되므로 주의.

 static getDerivedStateFromProps(props,state){
    // 여기서는 setState 를 하는 것이 아니라
  // 특정 props 가 바뀔 때 설정하고 설정하고 싶은 state 값을 리턴하는 형태로 사용.
  /*
  if (nextProps.value !== prevState.value) {
    return { value: nextProps.value };
  }
  return null; // null 을 리턴하면 따로 업데이트 할 것은 없다라는 의미
  */
 }

• 최초 마운트 시와 갱신 시 모두에서 render 메서드를 호출하기 직전에 호출
state를 갱신하기 위한 객체를 반환하거나, null을 반환하여 아무 것도 갱신하지 않을 수 있음

3. render

• 최종적으로 component에서 작업한 결과물을 return하는 method.
• component 라면 반드시 있어야 하는 method임!
• 함수형 컴포넌트에서는 render를 안쓰고 컴포넌트를 렌더링 가능
• React Element : 보통 JSX 를 사용하여 작성

❗️주의사항:
• Render() method는 순수(Pure Function)해야 함. (input에 대해서 같은 output이 나와야 한다는 것을 의미)
• DOM에 HTML을 표현
• 필수 메서드임!!!!!
• 시점이나 상황에 따라 다른 결과물을 리턴하는 것을 지양해야 함

render() {
	return (
      <div>
        <header className="title">
          Yuntroll React
        </header>
      </div>
	);
}

: 결과물로 나온 Element들이 Virtual DOM에 mount되고 실제 DOM에 업데이트됨.

4. componentDidMount

• 컴포넌트가 마운트(트리에 삽입)된 직 후 호출(컴포넌트가 마운트 될 때 한 번만 호출)
• 여기선 주로 D3, masonry 처럼 DOM 을 사용해야하는 외부 라이브러리 연동을 하거나, 해당 컴포넌트에서 필요로하는 데이터를 요청하기 위해 axios, fetch 등을 통하여 ajax 요청을 하거나, DOM 의 속성을 읽거나 직접 변경하는 작업을 진행함
→ DOM이 렌더링 되기 전에 DOM에 접근하게 되면 에러가 발생하기 때문
• 일반적으로 이 메서드에서 비동기 API를 사용
→ 응답받은 외부 데이터는 내부 컴포넌트 상태에 저장되어 컴포넌트가 업데이트 되면 render() 메서드가 실행

예시코드

import React, { Component } from "react";

class UserListClass extends Component {
  state = {
    loading: true,
    users: [],
  };

  componentDidMount() {
    fetch("https://jsonplaceholder.typicode.com/users")
      .then((response) => response.json())
      .then((users) => this.setState({ users, loading: false }));
  }

  render() {
    const { loading, users } = this.state;
    if (loading) return <div>Loading...</div>;
    return (
      <ul>
        {users.map((user) => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    );
  }
}

코드출처: https://www.daleseo.com/react-hooks-use-effect/

2️⃣ Updating(업데이트)

그러면 무엇을 기준으로 Updating 되는가?

  1. Props가 변경됨
  2. State가 변경됨
  3. 부모 component가 rerendering 됨
  4. this.forceUpdate로 강제로 렌더링을 trigger하는 경우
    → input이 달라지니 output도 달라져야 해서
    → 상위 component가 update되면 하위 component도 rendering 다시 mount

1. componentWillReceiveProps

• 컴포넌트가 새로운 속성을 전달받을 때 실행
• 컴포넌트에 새로운 속성을 받아오는 시점에 끼어들어서 render()를 호출하기 전에 일부 로직을 추가 가능
• 해당 메서드는 새로운 속성을 인자로 받음
• 컴포넌트 최초 실행할때는 렌더 ❌
• setState() 메서드를 호출해도 추가로 다시 렌더링이 발생 ❌
• 속성 값의 변경과 상관없이 (부모 구조 또는 호출에 따라) 재렌더링이 이뤄질 때마다 실행
→ newProps가 항상 현재 속성과 다른 값이라고 가정할 수 없음

예시코드

componentWillReceiveProps(newProps) {
  this.setState({
      opacity: (newProps.isVisible) ? 1 : 0
  })
}

: 기존 속성 값은 this.props 객체에 있음. 예를 들어 다음의 예제 코드는 불 값인 isVisible을 기준으로 하여, CSS에 사용할 opacity 상태 값을 변경한다(true이면 1, false이면 0).

출처: https://thebook.io/006961/part01/ch05/06/01/

2. shouldComponentUpdate

• props나 state를 변경 시, 리렌더링을 할지 말지 결정하는 메서드.
• 해당 메서드는 반드시 true 혹은 false를 반환해야함.
(해당 함수는 기본적으로 true를 반환, 조건에 따라 false 를 반환하면 해당 조건에는 render 함수를 호출 ❌)
• 오직 성능 최적화만을 위한 것이며 렌더링 목적을 방지하는 목적으로 사용하게된다면 버그로 이어질 수 있음

예시코드

shouldComponentUpdate(nextProps, nextState) {
  // return false 하면 업데이트 ❌
  // return this.props.checked !== nextProps.checked
  return true;
}

3. getSnapshotBeforeUpdate

• 업데이트 되기 직전에 snapshot(props & states)을 확보하는게 목적
• 인자값에서 반환되는 prevProps와 prevState는 변경되기 전에 값을 보여줌
• 컴포넌트에 변화가 일어나기 직전의 DOM 상태를 가져와서 특정 값을 반환하면 그 다음 발생하게 되는 componentDidUpdate 함수에서 받아와서 사용
ex) 렌더링을 하고 나서 업데이트하기 전에 스크롤의 위치, 해당 DOM의 크기 등을 가져오고 싶을 때 사용

예시코드

getSnapshotBeforeUpdate(prevProps,prevState){
   // DOM 업데이트가 일어나기 직전의 시점입니다. 
   return {};
}

❗️ 주의사항
• componentDidUpdate의 세번째 인자로 들어감
• 해당 함수와 componentDidUpdate 함수를 함께 적지 않는 경우 Warning 발생

4. componentWillUpdate()

• 새로운 속성이나 상태를 받은 후 렌더링 직전에 호출(초기 렌더링 시에는 호출 ❌)
• 주로 갱신 전에 필요한 준비 작업을 처리할 때 해당 메서드 사용(사용시 this.setState사용은 피하자! → 갱신중에 갱신...???)
• shouldComponentUpdate()가 false를 반환하면 해당 메서드는 실행 ❌
• 컴포넌트를 DOM에서 제거할 때 실행
• componentDidMount에서 등록한 이벤트, 타이머, 직접 생성한 DOM이 있다면 여기서 제거 작업 해야함!!!

예시코드

componentWillUpdate(nextProps, nextState){
}

5.componentDidUpdate

• state나 props가 변경되어 DOM 변화가 발생한 뒤 발생(리렌더링을 완료한 후 실행, 처음 렌더링 될때는 호출❌)
• 업데이트가 끝난 직후이므로, DOM관련 처리를 해도 무방
• prevProps 또는 prevState를 사용하여 컴포넌트가 이전에 가졌던 데이터에 접근 가능⭕️

❗️ 주의사항
componentDidUpdate()에서 setState()를 즉시 호출할 수도 있지만, ... 조건문으로 감싸지 않으면 무한 반복이 발생할 수 있다는 점에 주의해야함( break와 같은역할을 가진 조건문을 걸어줘야함, 실제 변경이 일어난 경우만 작동하도록 코드 작성)

예시코드

// Class
class Example extends React.Component {
    componentDidUpdate(prevProps, prevState, snapshot) {
        ...
    }
}

3️⃣ Unmounting(제거)

: DOM에서 제거되는 것, JSX 에 포함되었다가 이후에 제거되는 경우에 발생

언마운트 예시

return <div>
  {value ? <Comp1 /> : <Comp2 />}
  <button onClick={() =>
  setValue(!value)}>change</button>
</div>;

→ 초기에 value 가 true 인 상황에서 버튼을 클릭하면 Comp1 은 언마운트되고 Comp2 는 마운트 됨
→ 또 버튼을 클릭하면 Comp2 는 언마운트되고 Comp1 은 마운트 됨

<Comp1 key={value} />

→ key 가 변하는 경우도 언마운트 됨
→ 위 코드에서 value 가 변할 때마다 Comp1 는 언마운트되고 새로운 Comp1 이 마운트 됨

1. componentWillUnmount()

• 타이머를 제거하거나, DOM 요소를 정리하거나, componentDidMount()에서 연결한 이벤트를 제거가능
• 컴포넌트가 화면에서 사라지기 직전에 호출
• 외부 라이브러리를 사용한게 있고, 해당 라이브러리에 dispose 기능이 있다면 여기서 호출!

예시코드

class Example extends React.Component {
    coomponentWillUnmount() {
        ...
    }
}

4️⃣ Error Handling

1. componentDidCatch

• 컴포넌트 렌더링 도중에 에러가 발생 했을 때 애플리케이션이 멈추지 않고 오류 UI를 보여줄 수 있게 함

예시코드

// Class
class Example extends React.Component {
  componentDidCatch(error, info) {
    console.log('에러가 발생했습니다.')
  }
}
profile
코딩으로 세상에 이야기하는 개발자

0개의 댓글