본문 바로가기
🌳Frontend/react

React 에서 주의해야하는 Event 와 addEventListener

by Bㅐ추 2023. 3. 24.
728x90
반응형

원본글

https://medium.com/hcleedev/web-event%EC%99%80-addeventlistener-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0-%EA%B0%9C%EB%85%90-react%EC%97%90%EC%84%9C-%EC%A3%BC%EC%9D%98%ED%95%A0-%EC%A0%90-a581adc49aa4

https://joonior.tistory.com/96

https://babycoder05.tistory.com/entry/React-useEffect%EC%99%80-addEventListener-window-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A0%8C%EB%8D%94%EB%A7%81-%EA%B7%9C%EC%B9%99


Event

프로그램에서 발생하는 어떠한 사건.

주로 사용자와의 상호작용에서 나오거나, 비동기 작업 처리를 위해 만들어지기도 한다.

예시
어떤 요소를 클릭
어떤 요소 위에 올라가는 경우
키보드에서 어떤 키를 눌렀을 경우
사용자가 브라우저 창의 크기를 조정하는 경우

이러한 이벤트들을 자바스크립트에선 Event 인터페이스를 상속하고 있다.

이벤트에 맞추어 무언가 적절한 처리를 하고싶을 때 , 해당 이벤트에 함수를 등록할 수 있다.

이 함수를 event handler 라고 한다. 이벤트가 발생하면 event handler 가 실행된다. 이때 실행되게 해주는 것을 event listener 라고 한다.

어떤 특정 이벤트가 발생하는지 계속 지켜보다가(listening) , 이벤트가 발생하면 미리 등록해놓은 event handler 가 호출된다.

이때 event handler 를 event listener 에 연결하는 것을 등록이라고 하는데, 등록하는 방식은 여러가지가 있다.

 

이벤트 등록

1. 컴포넌트에 직접 넣어주는 방식

// HTML
<button onclick="handler()"></button>
// React
<button onClick={handler}></button>

2. Dom 에 직접 넣어주는 방식

var btn = document.getElementById("button");
btn.onclick = buttonClick();

3. addEventListener

const btn = document.querySelector('button');

function bgChange() {
  ...
}

btn.addEventListener('click', bgChange);

addEventListener('이벤트명', 실행할 함수) 로 등록할 수 있다.

이때 등록된 event listener 를 제거하는 함수도 존재한다 (removeEventListener)

 

이 방식을 사용하게 되면, 한 컴포넌트에 같은 이벤트에 대한 여러가지의 handler 들을 등록할 수 있다.

btn.addEventListener('click', bgChange1);
btn.addEventListener('click', bgChange2);

 

단, 이 방식을 React 에서 사용할 때 주의해야할 몇가지가 있다.


1. 메모리관리

const Component = () => {
  window.addEventListener('keydown', handleKeyDown);
  ...
}

 

 

위처럼 작성하게 되면, 해당 Component 가 리렌더링될 때 마다 window 에 handler 를 계속 추가하게 된다. 이것은 메모리 누수의 원인을 제공할 수 있다. 그러므로, 꼭 적절한 때에 등록한 이벤트리스너를 제거해주어야 한다. 주로 아래처럼 컴포넌트가 언마운트될 때 제거해준다.

  useEffect(() => {
    const onMouseMove = (e) => {
      setCirclePosition({left: e.clientX - 500, top: e.clientY - 500})
    };

    document.addEventListener('mousemove', onMouseMove);

    return () => {
      document.removeEventListener('mousemove', onMouseMove);
    }
  }, [])

 

2. 캡처링

아래의 코드를 보자.

버튼을 누르면 state 가 1씩 증가하고, 키보드 키를 누르면 state 를 출력하는 로직이다.

function App() {
  const [state, setState] = useState<number>(0);
  const handler = () => {
    console.log(state);
  }
  useEffect(() => {
    window.addEventListener('keydown', handler);
  }, []);
  return (
    <>
      <p>{'Current: ' + state}</p>
      <button onClick={() => {
        setState(state + 1);
      }}>add</button>
    </>
  );
}

하지만,실제로 실행해보면 0만 계속 찍힌다.

왜그럴까? 왜냐면 window.addEventListener 가 호출되는 시점에 handler 로 고정되어버리기 때문이다.

handler 안에서 호출하는 state 는 window.addEvent Listener 가 호출하는 시점의 딱 그 값을 가리키고 있다.

 

이경우에 크게 두가지의 해결법이 있는데,

 

1 . state 값을 useRef는 class든을 사용해 어떤 주소를 참조하도록 만들면, 값이 변경될 때마다 반영될 수 있다.
2. useEffect의 deps에 state를 추가
useEffect(() => {
  window.addEventListener('keydown', handler);
  return () => {
    window.removeEventListener('keydown', handler);
  }
}, [state]);

이렇게 하면 state 가 변경될 때마다 기존의 event Listener가 사라지고 새로운 값이 반영된 Event Listener가 추가된다.

 

 

 

728x90
반응형

'🌳Frontend > react' 카테고리의 다른 글

Stop Using useMemo Now  (0) 2023.04.18
React.memo vs useMemo vs useEffect  (0) 2023.03.24
[SWR] SWR 동작 시나리오  (0) 2023.03.22
[SWR] useSWR 장점  (0) 2023.03.22
[Jest] 설치 및 기본 실행  (0) 2023.03.21