React Event Handler

우동이·2022년 6월 7일
0

React

목록 보기
2/5
post-thumbnail
  • 리액트는 이벤트가 발생할 때 해당 이벤트 핸들러는 Event 객체를 받을 수 있습니다.
  • Event 객체는 래핑된 SyntheticEvent의 인스턴스를 전달합니다.
    • 일반적인 nativeEvent( 브라우저 기본 이벤트 )가 아닙니다.
  • SyntheticEvent는 자주 사용하는 stopPropagationpreventDefault를 포함하여 nativeEvent와 동일한 인터페이스를 제공합니다.
    • 만약 nativeEvent를 사용하려면 해당 속성도 SyntheticEvent에 있기 때문에 SyntheticEvent.nativeEvent 이렇게 접근하여 사용할 수 있습니다.
  • onClick 함수를 통해 이벤트 객체를 받았을 때 SyntheticEvent의 모습

1. SyntheticEvent 내부 요소

  • 크게 EventPluginEventpluginHub 존재

    • EventPlugin

      • nativeEvent와 대응하는 SyntheticEvent를 생성하고 이와 관련된 모든 dispatch를 수집하여 배열 형태(큐)로 반환합니다.

        • 해당 dispatch를 실행하지는 않습니다. ( 특정 플러그인 제외 )

        • 관련된 모든 dispatch를 수집하기 위해 리액트는 아래와 같이 capture and bubbling phase를 참조하면서 컴포넌트(DOM) 트리를 이중 순회하며 순서대로 큐에 넣습니다.

        • stopPropagation ( 버블링 방지 )과 같은 인터럽션은 동일한 SyntheticEvent 에 속한 함수의 실행만 방지합니다.

        • 같은 큐에 속한 dispatch의 실행만 방지

    • Event Plugin Hub

      • 앞서 설명한 EventPlugin들은 웹이 실행되면 Event Plugin Hub에 주입되며 configuration file에 따라 플러그인이 정렬됩니다.
      • 그다음 런타임에서 nativeEvent를 받을 때마다 다음 과정을 수행합니다.
        • 각 플러그인 마다 순서대로 모든 SyntheticEvent와 관련된 dispatch를 수집하고 그들을 큐에 저장합니다.
        • 큐에 있는 이벤트와 관련된 모든 dispatch를 실행 후 큐에서 삭제합니다.

2. nativeEvent 활용

  • SyntheticEvent에서 제공하는 stopPropagation은 오직 동일한 SyntheticEvent(큐)에 속한 dispatch 실행만 방지합니다.
    • 이벤트 플러그인 하나에서만 작동하기 때문에 동일한 이벤트를 같은 태그 안에 넣을 경우 stopPropagation이 동작하지 않을 수 있습니다.
  • 극단적인 예시
    • 해당 코드에서 stopPropagation를 통해 버블링을 방지하고 있지만 Event A와 Event B 중 한가지는 버블링 현상에 의해 이벤트가 발생할 것입니다.
      • A와 B중 하나의 이벤트는 다른 SyntheticEvent(큐)에 포함되어 있기 때문입니다.
    • 물론 동일한 이벤트를 하나의 태그안에 넣을 수 없도록 React에서 에러처리를 해주고 있지만 커스텀 이벤트를 통해 이름은 다르지만 같은 이벤트 일 경우 충분히 발생할 수 있다고 생각합니다.
    • SyntheticEvent에서 제공하는 stopPropagation으로 버블링을 해결할 수 없다면 nativeEvent를 활용해서 플러그인의 종류와 관계없이 stopPropagation를 활용할 때 사용하면 좋을 것 같습니다!
import React, { useTransition, useState, useId } from "react";

import "./App.css";

function App() {
  const event = new Event("build");
  document.dispatchEvent(event);

  return (
    <>
      <div
        customEvent_A={(evt) => console.log("event A")}
        customEvent_B={(evt) => console.log("event B")}
      >
        <div customEvent={(evt) => evt.stopPropagation()}>클릭</div>
      </div>
    </>
  );
}

export default App;

참고 문서

profile
아직 나는 취해있을 수 없다...

0개의 댓글