본문 바로가기
개발/React

useEffect cleanup은 state초기화 이후에 실행된다.

by 안뇽! 2022. 12. 10.
반응형

밑에 글 다 헛소리임. 클로저 문제임

요약

컴포넌트 언마운트 과정 : DOM업데이트 + useState 초기화 -> cleanup 실행 -> 언마운트


예전에 useEffect cleanup함수가 componentWillUpdate가 아니라 componentDidUpdate에서 실행된다는 것을 알게되어 을 쓴 적이 있다.

 

useEffect의 cleanUp 함수에 대한 착각 : unmount시 발생하는 것이 아니다!

들어가기에 앞서 결론부터 말하자면 공식문서에 나와있다! 실제 실험을 통해 페이지 이동(unmount)이 안되어도 setInterval을 정리하여 버그를 차단함을 알 수 있음 1. clean-up 없을 때 import { useEffect, us

wnsdufdl.tistory.com

 

사이드를 하다가 문제가 생겼다.

 

이렇게 컴포넌트가 리렌더링되어도 마커의 말풍선이 사라지지 않는 문제였다.

 

컴포넌트가 리렌더링 되기 전에 마커를 삭제하는 함수를 넣어야 하는데,

 

아래와 같이 작성하였을때, state가 초기화되면서 prevInfo가 undefined가 되어 cleanup 내부의 removeInfo가 실행되지 않았다.

const PlaceList = ({ places, map, prevMarkers, setPrevMarkers }: Props) => {

  const [prevInfo,setPrevInfo] = useState();
  ...

  useEffect(() => {
    console.log('마운트');
    return () => {
      console.log('리랜더링', prevInfo);
      removeInfo(prevInfo);
    };
  }, []);

.. 생략 ..

 

구글링을 해보니 useEffect의 cleanup 함수의 실행시점때문이었다.

 

  • 내 생각 : cleanup으로 뒷정리 -> DOM 업데이트 및 unmount
  • 실제 : DOM 업데이트 -> cleanup 으로 뒷정리 ( componentDidUpdate ) -> unmount

였다.

 

가만보니 이전에 정리했던 내용을 잊어버린 것이다.

 

여튼 위의 PlaceList가 리렌더링되는 과정은

 

DOM업데이트 + useState 초기화 -> cleanup 실행 -> 언마운트 였기에, cleanup 함수를 실행할 수 없었던 것이다.

useEffect(() => {
    console.log('마운트');
    return () => {
    //cleanup이 실행되기 전 이미 state가 초기화 되어
    //prevInfo 는 undefined 임
      console.log('리랜더링', prevInfo);
      removeInfo(prevInfo);
    };
  }, []);

 

해결책은 useState가 초기화 되지 않도록 상위컴포넌트에 정의하고 props로 받았다.

// prevInfo 상위컴포넌트에서 정의하고 props로 내려받음
const PlaceList = ({ prevInfo, setPrevInfo, .. }: Props) => {
...

  useEffect(() => {
    console.log('마운트');
    return () => {
      console.log('리랜더링', prevInfo);
      //prevInfo는 상위컴포넌트에 정의되어 있기 때문에, 
      //PlaceList의 DOM이 업데이트 될 때, 초기화되지 않음
      removeInfo(prevInfo);
    };
  }, []);

.. 생략 ..

 

이렇게 하니, 해당 컴포넌트가 업데이트 되어도 상위컴포넌트에서 props를 통해내려받은 props는 초기화 되지 않았고

이 덕분에 언마운트 직전에 removeInfo를 실행시킬 수 있었다.

 


요점은 다음과 같다

  • 문제 : DOM업데이트 + useState 초기화 -> cleanup 실행 -> 언마운트 를 인지하지 못했음
  • 해결 : cleanup에서 실행할 state를 상위 컴포넌트에 정의하여 DOM업데이트시 초기화 되지 않도록 함
반응형