이벤트 처리하기

</>·2022년 3월 23일
3
post-thumbnail

목표

  • 이벤트 처리하기에 대해 알아보기

6. 이벤트 처리하기

  • 리액트는 이벤트에 대해 다음과 같이 설명한다.

React 엘리먼트에서 이벤트를 처리하는 방식은 DOM 엘리먼트에서 이벤트를 처리하는 방식과 매우 유사합니다. 몇 가지 문법 차이는 다음과 같습니다.

  • React의 이벤트는 소문자 대신 캐멀 케이스(camelCase)를 사용합니다.
  • JSX를 사용하여 문자열이 아닌 함수로 이벤트 핸들러를 전달합니다.
  • 다음은 HTML과 React의 이벤트 핸들러를 전달하는 코드를 비교한 것이다.
<!-- HTML -->
<button onclick="activateLasers()">
  Activate Lasers
</button>
// React
<button onClick={activateLasers}>
  Activate Lasers
</button>

6-1. 합성 이벤트(SyntheticEvent)

  • HTML에서는 다음과 같이 false를 리턴하여 기본 동작을 방지할 수 있다.
<form onsubmit="console.log('You clicked submit.'); return false">
  <button type="submit">Submit</button>
</form>
  • 하지만, 리액트에서는 false를 반환해도 기본 동작을 방지할 수 없다.
  • 반드시 preventDefault를 명시적으로 호출해야 한다.
function Form() {
  function handleSubmit(e) {
    e.preventDefault();
    console.log('You clicked submit.');
  }

  return (
    <form onSubmit={handleSubmit}>
      <button type="submit">Submit</button>
    </form>
  );
}
  • 위 코드에서 handleSubmit의 매개변수 e를 합성 이벤트라고 한다. 자세한 내용은 여기에서 확인할 수 있다.
  • 이벤트 핸들러는 모든 브라우저에서 이벤트를 동일하게 처리하기 위한 이벤트 래퍼 SyntheticEvent 객체를 전달받는다.
export default function Event() {
  const onClick = (e) => {
    console.dir(e);
  };

  return (
    <div>
      <button onClick={onClick}>button</button>
    </div>
  );
}
  • SyntheticEvent 객체를 출력해보면 다음과 같다.

  • stopPropagation() 와 preventDefault()를 포함해서 인터페이스는 모든 브라우저에서 동일하게 동작한다.
  • 브라우저의 고유 이벤트가 필요하다면 nativeEvent 어트리뷰트를 참조하면 된다.
  • 또한, 합성 이벤트는 브라우저 고유 이벤트에 직접 대응되지 않으며 다르다.
  • 예를 들어, onMouseLeave에서 event.nativeEvent는 mouseout 이벤트를 가리킨다.

6-2. 이벤트 흐름(Event Flow)

  • DOM이벤트 흐름은 3단계로 이루어져 있다.
    1. 캡처링(Capturing) 단계
    2. 타켓(Target) 단계
    3. 버블링(Bubbling) 단계
<style>
  body * {
    margin: 10px;
    border: 1px solid blue;
  }
</style>

<form>FORM</form>

<script>
  for (let elem of document.querySelectorAll('*')) {
    elem.addEventListener("click", e => console.log(`캡쳐링: ${elem.tagName}`), true);
    elem.addEventListener("click", e => console.log(`버블링: ${elem.tagName}`));
  }
  
  document.querySelector("form").onclick = function () {
    console.log("click");
  };
</script>
  • form 태그를 클릭하게 되면 다음과 같이 동작한다.
// 결과
"Capturing: HTML"
"Capturing: BODY"
"Capturing: FORM"
"Bubbling: FORM"
"click"
"Bubbling: BODY"
"Bubbling: HTML"

  • 정리하면 캡처링 단계는 어떤 엘리먼트에 이벤트가 발생했는지 부모에서부터 자식으로 내려가면서 체크하는 과정을 말한다.
  • 버블링 단계는 이벤트가 발생한 엘리먼트에서부터 부모로 이벤트를 정리하는 것을 말한다. 실제 이벤트는 버블링 단계에서 일어난다.

6-2-1. 리액트에서의 이벤트 흐름

  • 리액트에서는 onClickCapture를 이용해서 캡처링 단계에서 벤트 핸들러를 사용할 수 있다.
export default function Event() {
  const onClickCaputreParent = () => {
    console.log("onClickCaputreDivParent");
  };

  const onClickCaputreChild = () => {
    console.log("onClickCaputreDivChild");
  };

  const onClickCaputreButton = () => {
    console.log("onClickCaputreButton");
  };

  const onClickBubbleParent = () => {
    console.log("onClickBubbleDivParent");
  };

  const onClickBubbleChild = () => {
    console.log("onClickBubbleDivChild");
  };

  const onClickBubbleButton = (e) => {
    console.log("onClickBubbleButton");
    console.log(e);
  };

  return (
    <div onClickCapture={onClickCaputreParent} onClick={onClickBubbleParent}>
      <div onClickCapture={onClickCaputreChild} onClick={onClickBubbleChild}>
        <button
          onClickCapture={onClickCaputreButton}
          onClick={onClickBubbleButton}
        >
          button
        </button>
      </div>
    </div>
  );
}

// 결과
"onClickCaputreDivParent"
"onClickCaputreDivChild"
"onClickCaputreButton"
"onClickBubbleButton"
SyntheticBaseEvent {_reactName: 'onClick', _targetInst: null, type: 'click', nativeEvent: PointerEvent, target: button,}
"onClickBubbleDivChild"
"onClickBubbleDivParent"

6-3. 이벤트 종류

  • 다음 이벤트들은 버블링 단계에서 호출된다. 자세한 내용은 여기에서 확인할 수 있다.
    • Clipboard 이벤트
    • Composition 이벤트
    • Keyboard 이벤트
    • Focus 이벤트
    • Form 이벤트
    • Generic 이벤트
    • Mouse 이벤트
    • Pointer 이벤트
    • Selection 이벤트
    • Touch 이벤트
    • UI 이벤트
    • Wheel 이벤트
    • Media 이벤트
    • Image 이벤트
    • Animation 이벤트
    • Transition 이벤트
    • 기타 이벤트
  • 위의 이벤트 중 Focus 이벤트를 살펴보면 다음과 같다.
    • onFocus
      • 엘리먼트(또는 자식 엘리먼트)가 포커스될 때 호출된다.
      • 예를 들어 input을 클릭해 포커싱되면 콘솔을 출력한다.
    • onBlur
      • 엘리먼트 (또는 자식 엘리먼트)에서 포커스가 사라졌을 때 호출된다.
      • 예를 들어 포커싱된 input에서 다른 엘리먼트로 포커싱되면 콘솔을 출력한다.
function Example() {
  return (
    <input
      onFocus={(e) => {
        console.log('Focused on input');
      }}
      onBlur={(e) => {
        console.log('Triggered because this input lost focus');
      }}
      placeholder="onFocus is triggered when you click this input."
    />
  )
}

출처

profile
개발자가 되고 싶은 개발자

0개의 댓글