Post

커스텀 이벤트 만들기

⭐ Custom Event 활용하기

Next로 작업을 하는 와중에, 다음과 같은 상황이 있었다.

  1. layout.tsx에 특정 페이지와 하위 페이지에서만 적용 될 컴포넌트가 있는데, 여기에 undo / redo 버튼이 있다.

  2. 하지만 실제 undo / redo가 되어야 하는 건 edit 페이지 안에 있다.

  3. layout.tsx는 edit 페이지에 직접적으로 state를 전달할 수 없다.

이런 상황에서 undo / redo를 완성하려면 전역 상태 관리밖에 답이 없을까? 👀 사실 그런줄 알았는데 또 다른 방법이 있었다. 바로 브라우저의 CustomEvent다.

🎁 예제 살펴보기

MDN의 예제를 살펴보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// CustomEvent 생성
const catFound = new CustomEvent("animalfound", {
  detail: {
    name: "cat",
  },
})

// 이벤트 수신기 등록
obj.addEventListener("animalfound", (e) => console.log(e.detail.name))

// 이벤트 발동
obj.dispatchEvent(catFound)

// 콘솔: cat

예제에서는 먼저 new CustomEvent를 통해 animalfound라는 사용자 정의 이벤트 객체를 생성했다. 이때 detail이란 이벤트에 담아 보낼 데이터를 실어두었다.

이미 설정되어있는 click 이벤트처럼 addEventListener를 활용해 미리 만들어 둔 animalfound이벤트를 실행시킨다.

이때 e에는 미리 만들어 둔 catFound 객체가 전달된다.

1
2
3
4
5
6
e = {
  type: "animalfound",
  detail: {
    name: "cat",
  },
}

그래서 최종적으로 콘솔에 cat이 찍히게 된다.

1
2
3
4
5
6
7
// 이벤트 수신기 등록
obj.addEventListener("animalfound", (e) => console.log(e.detail.name))

// 이벤트 발동
obj.dispatchEvent(catFound)

// 콘솔: cat

👍 내 코드에 적용하기

그러면 undo와 redo를 만들어보자.

1
2
3
const handleUndo = () => {
  window.dispatchEvent(new CustomEvent("undo"))
}

먼저 layout.tsx에 사용자가 클릭할 버튼을 만들고 onClick이벤트를 눌렀을 때 함께 발생할 커스텀 이벤트를 등록한다.

1
2
3
4
5
6
7
8
9
useEffect(() => {
  const handleUndoEvent = () => handleUndo()

  window.addEventListener("undo", handleUndoEvent)

  return () => {
    window.removeEventListener("undo", handleUndoEvent)
  }
}, [handleUndo])

그 다음 edit 페이지에서 undo 이벤트가 발생할 경우 실행할 수 있도록 기다리는 useEffect를 작성한다.

그리고 실제 undo 이벤트가 발생시 어떻게 작동해야 하는지에 대한 handleUndo함수를 작성한다.

1
2
3
const handleUndo = useCallback(() => {
  //코드 작성
}, [storeUndo])

즉 최종 흐름은 다음과 같다.

1
2
3
4
5
6
7
8
9
layout 버튼 클릭
      ↓
dispatchEvent('undo')
      ↓
edit에서 이벤트 감지
      ↓
handleUndo()
      ↓
실제 undo 로직 실행

이렇게 하면 간단하게 원하는 기능을 구현할 수 있다.

This post is licensed under CC BY 4.0 by the author.