[React] EventListener 추가하고 반드시 제거하기

JUNG MINU·2023년 3월 29일
0

React LifeCycle

리액트의 함수형 컴포넌트를 사용할 때 LifeCycle을 아는 것과 모르는 것의 차이는 매우 크다.

리액트 프레임워크를 사용해서 프로젝트까지 해봤는데도 불구하고 오늘도 엄청난 실수를 하나 했는데,
다신 실수하지 않도록 기록을 남겨놓는다.

addEventListener

import { useState } from "react";

...

const [scrollLocation, setScrollLocation] = useState<number>(0);

const windowScrollListener = (e: Event) => {
  setScrollLocation(document.documentElement.scrollTop);
  console.log(scrollLocation);
};
  
window.addEventListener("scroll", windowScrollListener)

...

함수형 컴포넌트가 렌더링 되면 scroll의 위치를 state에 지속적으로 최신화하는 함수이다.
useState는 state에 선언된 값이 바뀔 때 마다 연관된 컴포넌트들을 새로 렌더링해줘서 값을 바꿔주거나, 역동적인 화면 요소를 그릴 수 있게 해준다.
window에 scroll event가 발생할 때 마다 scrollLocation state를 바꿔준다.
위 코드는 타입스크립트로 작성한거라서 타입선언이 되어있다.

그런데...

근데 이런식으로 코드를 작성하면 정말 큰일난다.
이유는 페이지를 벗어나도 event listener가 사라지지 않기 때문.

미친듯이 중복된 listener가 작동해서
스크롤 한번에 만개씩 console.log가 쌓이는 모습을 볼 수 있다....

useEffect

아, 그렇다면 addEventListener() 메서드가 최초 1회만 실행되게 하면 되겠구나.

useEffect는 React의 LifeCycle을 쉽게 이용할 수 있게 해준다.
useEffect의 두번째 인자에 들어오는 리스트 안의 값이 변할 때 useEffect에 선언된 함수가 실행된다.
빈 리스트를 넣게 되면 최초 1회만 실행된다.

import { useEffect, useState } from "react";

...

const [scrollLocation, setScrollLocation] = useState<number>(0);

const windowScrollListener = (e: Event) => {
  setScrollLocation(document.documentElement.scrollTop);
  console.log(scrollLocation);
};
  
useEffect(() => {
  window.addEventListener("scroll", windowScrollListener);
}, []);

...

안된다.
이유는 window에 listener를 달아버린 나머지
해당 컴포넌트를 벗어나도 listener 제거가 되지 않는다.
무조건 해당 컴포넌트를 벗어날 때 listener를 제거해야 한다.
이럴때 사용하는 것이 useEffect의 return 함수

import { useEffect, useState } from "react";

...

const [scrollLocation, setScrollLocation] = useState<number>(0);

const windowScrollListener = (e: Event) => {
  setScrollLocation(document.documentElement.scrollTop);
  console.log(scrollLocation);
};
  
useEffect(() => {
  window.addEventListener("scroll", windowScrollListener);
  return () => {
    window.removeEventListener("scroll", windowScrollListener);
  };
}, []);

...

이게 최종 코드이다.
return 뒤에 오는 함수의 값은 해당 컴포넌트가 제거될 때 실행되는 함수이다.
컴포넌트가 제거될 때 event listener를 제거해서 자원 낭비가 일어나지 않도록 한다.

편안..

반드시 한 컴포넌트에서 만든 listener는 해당 컴포넌트에서 제거하자.

profile
감각있는 프론트엔드 개발자 정민우입니다.

0개의 댓글