[React] 라이프 사이클

정예원·2022년 4월 10일
0

React

목록 보기
6/7
post-custom-banner

react의 각각의 컴포넌트는생성 -> 업데이트 -> 제거 단게를 차례로 겪는 생명주기(Life Cycle)을 가지고 있다.

크게 3가지로 나눌 수 있다.
생성(mount), 업데이트(update), 제거(unmount) 이다.

마운트는 컴포넌트 함수가 실행되고 결과물로 나온 Element들이 virtualDOM에 삽입되고 실제DOM을 업데이트하기까지의 과정이다.
언마운트는 DOM에서 제거되는 것이다.

🎉 mount

constructor -> render -> componeneDidMount

constructor

react 컴포넌트의 생성자는 해당 컴포넌트가 마운트되기 전에 호출한다.
1. this.state로 state 값을 선언/초기화
2. 이벤트 처리 메서드를 바인딩

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

주의할 점
1. 메서드를 바인딩하거나 state를 초기화하는 작업이 없다면, 해당 React 컴포넌트에는 생성자를 구현하지 않아도 된다.
2. super(props)를 호출하지 않으면 this.props가 생성자 내에서 정의되지 않아 버그로 이어질 수 있다.
3. constructor 내부에서 setState 등의 업데이트를 실행하지 말자. 필요하다면 state에서 정의하면 된다. Mount 되기 전에 업데이트를 하는 것은 바람직하지 않다.
해당 경우에는 componentDidMount() 를 사용하자.

render

클래스 컴포넌트에서 반드시 구현돼야하는 유일한 메서드이다.
이 메서드가 호출되면 this.propsthis.state의 값을 활용하여 아래의 것 중 하나를 반환해야 한다.

  • react 엘리먼트 : 보통 jsx를 사용해 생성
	render() {
      return (
        <div>yeewon</div>
      );
	}
  • 배열과 fragment : render()를 통해 여러 개의 엘리먼트를 반환
    render() {
      const ButtonList = lists.map((data, index) => {
        return (
          <button key={index} type="button">
            {data}
          </button>
        );
      });

        return (
          // 여러 자식을 그룹화 -> 단축 문법 <></>
            <Fragments>
                {ButtonList}
            </Fragments>
        );
    }
  • portal : 별도의 DOM 하위 트리에 자식 엘리먼트를 렌더링
  • 문자열과 숫자
  • boolean 또는 null
	render() {
      return (
        {isLogin && <Login />}
      );
	}

주의할 점
1. render() 함수는 순수해야 한다.

순수하다 = 컴포넌트의 state를 변경하지 않고, 호출될 때마다 동일한 결과를 반환해야 한다. 브라우저와 직접적으로 상호작용 하지 않는다.


2. render() 내에서 setState를 하면 안된다. render에서 state를 업데이트하면 render를 호출하고...무한 루프에 빠진다.

componentDidMount

컴포넌트가 마운트된 직후, 즉 트리에 삽입된 직후에 호출된다. 데이터 구독을 설정하기 좋은 위치이다.

  • DOM 노드가 있어야 하는 초기화 작업이 있는 경우 적절하다. 예를 들면, 모달 또는 툴팁 같이 앞서 DOM 노드의 크기나 위치를 먼저 측정해야 하는 경우에 적절하다.
  • 외부에서 데이터를 불러와야 한다면, 네트워크 요청을 보내기 적절하다.

✏️ Update

( New props, setState, forceUpdate ) -> render -> componentDidUpdate

업데이트는 아래 4가지 상황에서 발생한다.

1. props가 바뀔 때 
2. state가 바뀔 때 
3. 부모 컴포넌트가 리렌더링 될 때
4. this.forceUpdate가 강제로 렌더링을 트리거할 때

componentDidUpdate

갱신이 일어난 직후에 호출된다.

  • 컴포넌트가 갱신되었을 때 DOM을 조작하기 위하여 이 메서드를 활용하면 좋다.
  • 이전과 현재의 props를 비교하여 네트워크 요청을 보내는 작업이 이루어진다.
  componentDidUpdate(prevProps) {
    // 전형적인 사용 사례 (props 비교를 잊지 마세요)
    if (this.props.userID !== prevProps.userID) {
      this.fetchData(this.props.userID);
    }
  }

주의할 점
1. componentDidUpdate()에서 setState()를 즉시 호출할 수도 있지만, 위의 예시처럼 조건문으로 감싸지 않으면 무한 반복이 발생할 수 있다는 점에 주의해야 한다.

2. 상위에서 내려온 prop을 그대로 state에 저장하는 것은 좋지 않으며, 그 대신 prop을 직접 사용하는 것이 좋다.
참고 자료

🔚 Unmount

componentWillUnmount

컴포넌트가 마운트 해제되어 제거되기 직전에 호출된다.
타이머 제거, 네트워크 요청 취소, componentDidMount() 내에서 생성된 구독 해제 등 필요한 모든 정리 작업을 수행한다.
컴포넌트 인스턴스가 마운트 해제되고 나면, 절대로 다시 마운트되지 않는다.

총정리

예시를 통해서 흐름 정리를 해보았다.
결국 마운트가 된 후 상태가 변경되면 react는 리렌더링을 한다. (render 메서드를 다시 호출한다.)
이 두번째 render는 마운트하지 않고 DOM을 업데이트한다.

function App() {
  const [showUser, setShowUser] = useState(false)

  return (
    <div>
      {showUser && <User name="Brad" />}
      <button onClick={() => setShowUser(true)}>
        Show User
      </button>
      <button onClick={() => setShowUser(false)}>
        Hide User
      </button>
    </div>
  )
}
// React starts renders our component and since this is the
// first render, it "mounts" the component to the DOM:
App()

// Then state changes and React now needs to re-render the
// component with the new state in place:
App()

// State changes again, React re-renders again:
App()

처음, App은 render되어 mount되지만 showUser가 false이므로 User는 mount되지 않는다.
이 후 showUser가 true가 되면, App은 리렌더되고 User는 처음 렌더가 되고 mount된다.

이 후 state값이 바뀌고 App이 리렌더된다. 이전 render와 비교하고, react는 마운트 되었던 User가 App의 일부가 아니게 되므로 DOM으로부터 User가 unmount된다.

각각의 컴포넌트는 자신만의 스케줄이 있다. 부모 자식 관계에서는 부모가 마운트된 경우에만 자식 컴포넌트가 render와 mount가 일어난다. 또한 부모 컴포넌트가 unmount되었을때 자식 또한 unmount된다.

궁금했던 점

마운트 과정이 constructor -> render -> componentDidMount 인데
constructor가 마운트 전, componentDidMount가 마운트 직후 이니까
결국 render메서드를 호출하는 것이 mount되는 것인가?
아니다.
render와 마운트 개념에 대해 모호해서 생긴 문제였다.
정리하면 맨 처음 컴포넌트가 render될 때는 컴포넌트가 mount되지만, props나 state가 변경되어 render될때는 mount가 되지 않는다.

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

profile
hello world!
post-custom-banner

0개의 댓글