Suzie's Blog

[Next.js / TypeScript] custom hook : useEventListener 본문

개발/Next.js

[Next.js / TypeScript] custom hook : useEventListener

Iuna 2025. 2. 24. 14:18
반응형
SMALL

개발할때 유용하게 사용한 useEventListener hook 이다. (Next.js, TypeScript)

src > utils > hooks 에 저장 후 import하여 사용 하면 코드도 간편해지고 편함.

import { useEffect, useRef } from "react";

function useEventListener<K extends keyof WindowEventMap>(
  eventType: K,
  handler: (event: WindowEventMap[K]) => void,
  element: HTMLElement | Document | Window | null = typeof window !==
  "undefined"
    ? window
    : null
) {
    const savedHandler = useRef<(event: WindowEventMap[K]) => void | null>(null);

  useEffect(() => {
    savedHandler.current = handler;
  }, [handler]);

  useEffect(() => {
    if (!element) return;

    const eventListener = (event: Event) => {
      if (savedHandler.current) {
        savedHandler.current(event as WindowEventMap[K]);
      }
    };

    element.addEventListener(eventType, eventListener);
    return () => element.removeEventListener(eventType, eventListener);
  }, [eventType, element]);
}

export default useEventListener;

- `useEventListener` Hook은 언제 사용할까?

이 Hook은 컴포넌트에서 이벤트 리스너를 쉽게 추가/제거하기 위해 사용됨.

1. 전역 이벤트 (window, document) 감지

- scroll, resize, keydown, mousemove 같은 전역 이벤트를 감지할 때 유용

- 컴포넌트가 언마운트 될 때 자동으로 이벤트를 제거하기 때문에 메모리 누수 방지 가능

 

2. 키보드 입력 감지 (keydown, keyup)

- 사용자가 특정 키(Esc, Enter 등)를 누르면 동작

3. 마우스 이벤트 감지 (mousemove, click, mouseover)

- 특정 요소 바깥을 클릭하면 닫히는 기능 (예: 드롭다운 메뉴)

4. 특정 요소의 이벤트 감지

- 특정 div, button, input 등 특정 요소의 이벤트를 감지하고 싶을 때 사용.

 

useEventListener Hook을 사용하면 좋은 점

1. 이벤트 추가/제거를 자동화 -> useEffect로 수동관리할 필요가 없음.

2. 메모리 누수 방지 -> 컴포넌트 언마운트 시 자동으로 이벤트 제거

3. 전역 및 특정 요소 이벤트를 쉽게 감지 가능

코드에 관해 궁금했던 부분

- <K extends keyof WindowEventMap> 이란?

이 부분은 TypeScript의 제네릭(Generic) 문법을 사용하여 K가 WindowEventMap의 키 값 중 하나가 되도록 제한하는 코드.
WindowEventMap은 TypeScript에서 제공하는 내장 타입 : 브라우저에서 발생할 수 있는 모든 이벤트를 포함하는 객체
keyof WindowEventMap 은 모든 키를 가지고오는 유니온 타입
K extends keyof WindowEventMap에서 K는 "click", "keydown" 등 문자열만 가능하도록 제한
다른 변수명 사용해도 문제는 없지만 일반적으로 "K"를 사용 함. 제네릭에서 "K"는 "key"를 의미

  const savedHandler = useRef<(event: WindowEventMap[K]) => void>();

위에서 useRef를 사용한 이유는 이벤트 리스너가 최신 핸들러를 참조하도록 유지하면서 리렌더링 방지 가능

반응형
LIST