componentDidMount 와 useEffect

용상윤·2021년 2월 19일
6

리액트 훅을 공부하면서, class component 기반 코드와 hook을 이용한 코드를 비교하던 중에 풀리지 않는 문제가 생겼다.

처음에는 "Loading..." 을 렌더링하다가 3초 후에 "we are ready" 를 렌더링 하는 (비교적 매우 간단한...) 예제이다.

📌 문제

import React, { Component } from "react";

class App extends React.Component {
  state = {
    isLoading: true,
  };

  componentDidMount() {
    setTimeout(() => {
      this.setState({
        isLoading: false,
      });
    }, 3000);
  }

  render() {
    return 
    <div>
      {this.state.isLoading ? "Loading..." : "we are ready"}
    </div>;
  }
}

export default App;

이렇게 class로 작업을 하면, render() 함수가 실행 된 뒤에 그대로 값을 유지하기 위해서 componentDidMount() 를 쓰는 것 까지는 이해가 됐는데, 이 코드를 hooks 코드로 변형을 해보니 (👇 아래 코드)

import React, { useState } from "react";

const App = () => {
  const [isLoading, setIsLoading] = useState(true);

  setTimeout(() => {
    setIsLoading(!isLoading);
  }, 3000);

  return <h1>{isLoading ? "Loading" : "we are ready"}</h1>;
};

export default App;

잘 되는 것 같이 보였지만 Loading → we are ready → Loading → we are ready → Loading ... 이렇게 계속 렌더링이 반복 되었다.

상태가 바뀌어서 그런가? 하고

setTimeout() 부분을

useEffect(() => {
    setTimeout(() => {
      setIsLoading(!isLoading);
    }, 3000);
  });

useEffect()로 감싸주었는데도 계속 반복...

처음으로 stackoverflow 에 질문을 해봤는데 1시간도 지나지 않아 댓글이 달렸다! 😂


https://stackoverflow.com/questions/66275467/why-does-the-codefuntional-for-the-hook-keep-rendering-compared-to-class

답변

함수형 컴포넌트는 계속해서 렌더링이 된다고 한다. useEffect() 를 쓰는 접근은 맞았지만 끝에 ,[] 를 추가해 줘야 한다는 것.

위 링크의 리액트 document 를 참고해보니,

효과종속성이 너무 자주 변경되는 경우
빈 종속성 집합은 []구성 요소가 마운트 될 때마다 효과가 한 번만 실행되고 모든 다시 렌더링시 실행되지 않음을 의미합니다.


📌 정리

처음 클래스 컴포넌트에서, componentDidMount() 는 rendering이 모두 끝난 후 실행 되는 함수이므로 문제가 발생하지 않는다.

하지만 함수형 컴포넌트에서는 위 예제처럼 계속해서 redering이 되는 경우, 반복되는 life cycle을 막기 위해 state가 변경된 후 빈 배열로 mount를 지정해주어야 한다.

추가

useEffect(() => {
    setTimeout(() => {
      setIsLoading(false);
    }, 3000);
  });

setIsLoading 값을 아예 boolean으로 주면 re-rendering이 발생하지 않음.

profile
달리는 중!

2개의 댓글

comment-user-thumbnail
2022년 3월 10일

최근 class형으로 componentDidMount() 코드 구성을 연습해보다가 hooks로 바꿔보고 싶어 자료를 찾아보던 중이었는데 덕분에 도움이 되었습니다. 감사합니다!! 😁

1개의 답글