LifeCycle과 useEffect

KyungminLee·2021년 6월 22일
1

😃 LifeCycle

클래스 컴포넌트를 사용해본 경험이 있는 경우 LifeCycleuseEffect의 차이를 확실히 알고 넘어가는 것이 좋다.

👉 LifeCycle Method

다음 세개의 메소드가 핵심이다.
1. 컴포넌트가 마운트될 때 : componentDidMount
2. 컴포넌트가 리렌더링될 때 : componentDidUpdate
3. 컴포넌트가 마운트 해제되기 전에 : componentWillUnmount

LifeCycle Method 는 생명주기 메서드라고 부른다. 생명주기 메서드는 컴포넌트가 브라우저상에 나타나고, 업데이트되고, 사라지게 될 때 호출되는 메서드이다. 추가적으로 컴포넌트에서 에러가 났을 때 호출되는 메서드도 있다.

클래스 컴포넌트의 라이프 사이클은 다음과 같다.

1. Mounting(생성)

Component가 새롭게 생성되는 시점이다. Component 함수가 실행되고 결과물로 나온 Element들이 가상 DOM에 삽입되고 실제 DOM을 업데이트하기까지의 과정이다. 여기서 Mount는 컴포넌트가 처음 실행된 걸 말한다.

  • counstructor() : 컴포넌트의 state 초기값을 정의한다, 컴포넌트에서 사용되는 이벤트 핸들러를 바인딩 한다
  • render() : this.propsthis.state 값을 검증하며, 반환값을 화면에 렌더링시킨다. render() 내부에서 this.state값을 변경하면 무한 업데이트가 일어날 수 있으므로, 순수함수로 작성되어야 한다.
render() {
  return (
    <div>
      <SomeComponent />
      <OtherComponent />
    </div>
  )
}
  • componentDidMount() : componentDidMount()는 컴포넌트가 최초로 마운팅 된 이후 1회 실행된다. 그래서 다음과 같은 목적을 위해 주로 사용된다.

(1) 이벤트 리스너 등록 및 ajax 처리
(2) setTimeout, setInterval 실행

componentDidMount에서 바로 setState를 실행할 경우, 렌더링이 완료되고 다시 업데이트하여 또 다시 렌더링을 하게 된다. 하지만 이 경우에는 사용자는 2번 실행되는 렌더링 과정을 볼 수 없다. 브라우저에 화면을 갱신하기 전 실행되기 때문이다.

하지만 이렇게 2번 렌더링 되는 과정은 성능상으로 문제를 일으킬 수 있으므로 주의가 필요하다. 필요한 경우를 제외하면 최초에 실행되는 생성자(constructor)에서 세팅해야 한다.

2. Update(업데이트)

Component들은 stateprops 가 변경이 되면 update가 진행이 되며 다시 rendering 된다.

component가 update될 때 아래의 순서대로 메소드가 실행이 된다.
1. New Props / setState()
2. render()
3. componentDidUpdate()

  • New Props / setState() : 상위 Component로부터 갱신된 props 를 받는 경우 / 현재 자신이 가진 state를 변경하는 경우

  • componentDidUpdate : componentDidUpdate 는 update 가 이루어지고 render가 완료된 직후 실행되는 메소드이다. 최초 마운트 될 때는 실행되지 않는다.

componentDidUpdate 를 이용할 때, setState를 주의해야 한다. 조건문 등으로 제어해두지 않으면 무한 루프에 빠질 수 있기 때문이다.

setState > componentDidupdate > SetSate ...

3. Unmount(제거)

해당하는 Component가 DOM상에서 제거가 될 때 실행되는 lifeCycle이다.

주로 componentDidMount()에서 등록한 이벤트 리스너, setInterval, setTimeout을 클리어 하거나 외부 라이브러리 인스턴스 제거 등에 사용된다.

😄 useEffect

React Hook에서는 useEffect를 통해 react클래스의 componentDidMount나 componentDidUpdate, componentWillUnmount와 같은 목적으로 lifeCycle를 관리한다.

👉 useEffect deps

다음 사진으로 모든 것이 정리가 된다.

1. useEffect deps가 빈 배열의 경우

useEffect(() => {
  
}, [])

useEffect deps가 빈 배열의 경우 처음 Mount(첫 rendering) 될 때 호출된다.
componentDidMount()와 비슷하다.

2. useEffect deps에 특정 state가 있을 경우

만약 useEffect 함수 안에 의존성 배열을 명시하지 않고 state를 변경하는 작업을 한다면 무한루프가 발생한다. 아래와 같이 말이다..

const Example = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    setCount(count + 1); //무한루프 발생
  });

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>{count}</button>
    </div>
  );
};

이를 막기 위해서는 이렇게 두 번째 인자로 의존성 배열(deps)을 명시해줘야 한다. 리액트는 컴포넌트가 변경된다고 하더라도 count가 달라졌나 확인하고 달라지지 않았다면 effect를 실행하지 않을 것이다. componentDidUpdate()와 비슷하다.

const Example = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {}, [count]); //count가 변경되었을때에만 useEffect 실행

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>{count}</button>
    </div>
  );
};

3. useEffect deps가 없을 경우

const UseEffectExample = () => {
  const [test, setTest] = useState('initial value');
  useEffect(() => {
    console.log('렌더링!');
  });

  return (
    <div>
      <p>{test}</p>
      <input onChange={(e) => {setTest(e.target.value)}} />
    </div>
  )
}

다음 사진을 보면 해당 컴포넌트가 렌더링 될 때마다 useEffect함수가 실행되면서 콘솔에 로그를 남긴다. 다시 말하면 rendering 이후 componentDidUpdate() 가 계속 실행되는 것과 비슷하다.

4. useEffect의 Clean-up event

clean-up event는 react가 DOM에 그리고 난 이후에 실행이 된다. 아래는 매초마다 count를 1씩 올려주는 코드의 예시이다. 쉽게 생각하면 useEffect를 뒷정리 해주는 거라고 생각하면 된다. 주로 setInterval이나 setTimeOut과 같은 함수들을 사용할 때 사용한다.

function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const id = setInterval(() => {
      setCount(count + 1);
    }, 1000);
    return () => clearInterval(id);
  }, [count]);

  return (
    <>
      <h1>{count}</h1>
    </>
  );
}

👀 참고자료

1. react 공식문서
2. react useEffect hook 번역 블로그
3. useEffect 관련 블로그

profile
끊임없이 발전해가는 개발자.

1개의 댓글

comment-user-thumbnail
2024년 9월 8일

잘 읽었습니다. 감사합니다

답글 달기