[React] 이벤트 처리

김건휘·2024년 8월 16일
0

React

목록 보기
6/19
post-thumbnail

참고링크

📌이벤트 전파

이벤트 핸들러는 해당 컴포넌트가 가진 어떤 자식 컴포넌트의 이벤트를 수신할 수 있다. 이를 이벤트가 트리를 따라 “bubble” 되거나 “전파된다”고 표현합니다. 이때 이벤트는 발생한 지점에서 시작하여 트리를 따라 위로 전달됩니다.

📌예시 코드

export default function Toolbar() {
  return (
    <div className="Toolbar" onClick={() => {
      alert('You clicked on the toolbar!');
    }}>
      <button onClick={() => alert('Playing!')}>
        Play Movie
      </button>
      <button onClick={() => alert('Uploading!')}>
        Upload Image
      </button>
    </div>
  );
}

위 코드의 <div>는 두 개의 버튼을 포함하고 있습니다. <div> 그리고 각각의 버튼은 각자의 onClick 핸들러를 가지고 있습니다. 버튼을 클릭한다면 어느 핸들러가 작동하게 될까?

둘 중의 어느 버튼을 클릭하더라도 해당 버튼의 onClick이 먼저 실행될 것이며 이후 부모인 <div>의 onClick이 뒤이어 실행될 것입니다. 따라서 두 개의 메시지가 표시될 것이다. 만약 툴바 자체를 클릭한다면 오직 부모인 <div>의 onClick 만이 실행될 것이다.

버튼을 클릭했을 때는 버튼의 onClick만 실행되게 하고 싶다면???

📌전파 멈추기

이벤트 핸들러는 이벤트 오브젝트를 유일한 매개변수로 받는다. 관습을 따르자면 “event”를 의미하는 e로 호출되는 것이 일반적이다. 이 오브젝트를 이벤트의 정보를 읽어들이는데 사용할 수 있다.

이러한 이벤트 오브젝트는 전파를 멈출 수 있게 해준다. 이벤트가 부모 컴포넌트에 닿지 못하도록 막으려면 e.stopPropagation()를 호출하면 된다.

 function Button({ onClick, children }) {
 return (
   <button onClick={e => {
     e.stopPropagation();
     onClick();
   }}>
     {children}
   </button>
 );
}

export default function Toolbar() {
 return (
   <div className="Toolbar" onClick={() => {
     alert('You clicked on the toolbar!');
   }}>
     <Button onClick={() => alert('Playing!')}>
       Play Movie
     </Button>
     <Button onClick={() => alert('Uploading!')}>
       Upload Image
     </Button>
   </div>
 );
}

버튼 클릭시 절차

  1. React가 <button>에 전달된 onClick 핸들러를 호출.
  2. Button에 정의된 해당 핸들러는 다음을 수행.
  • e.stopPropagation()을 호출하여 이벤트가 더 이상 bubbling 되지 않도록 방지.
  • Toolbar 컴포넌트가 전달해 준 onClick 함수를 호출합니다.
  1. Toolbar 컴포넌트에서 정의된 위 함수가 버튼의 alert를 표시.
  2. 전파가 중단되었으므로 부모인 <div>의 onClick은 실행되지 않는다.

e.stopPropagation()의 결과, 버튼을 클릭하는 것은 이제 <button>과 그 부모인 툴바의 <div>가 보내는 두 개의 alert를 표시하지 않고 단 하나의 <button> alert 만을 표시합니다.

📌전파의 대안으로 핸들러를 전달하기

기본동작 예시

export default function Signup() {
return (
  <form onSubmit={() => alert('Submitting!')}>
    <input />
    <button>Send</button>
  </form>
);
}

<form>의 제출 이벤트는 그 내부의 버튼을 클릭 시 페이지 전체를 리로드하고 있음

개선 코드

export default function Signup() {
return (
  <form onSubmit={e => {
    e.preventDefault();
    alert('Submitting!');
  }}>
    <input />
    <button>Send</button>
  </form>
);
}

전체 리로드가 발생하지 않도록 막기 위해 e.preventDefault()를 이벤트 오브젝트에서 호출

e.stopPropagation()와 e.preventDefault()

  • e.stopPropagation()은 이벤트 핸들러가 상위 태그에서 실행되지 않도록 한다.
  • e.preventDefault() 는 기본 브라우저 동작을 가진 일부 이벤트가 해당 기본 동작을 실행하지 않도록 방지.

요약

  • <button>과 같은 요소에 함수를 prop으로 전달하여 이벤트를 처리할 수 있다.
  • 이벤트 핸들러는 호출이 아니라 전달만 가능합니다! onClick={handleClick()}이 아니라 onClick={handleClick}이다.
  • 이벤트 핸들러 함수는 별개의 함수 혹은 인라인 형태로 정의할 수 있다.
  • 이벤트 핸들러는 컴포넌트 내부에서 정의되기에 다른 prop에 접근할 수 있다.
  • 이벤트 핸들러는 부모에서 선언하여 자식에게 prop으로 전달할 수 있다.
  • 사용자 정의 이벤트 핸들러의 이름을 애플리케이션에 특화된 이름으로 명명할 수 있다.
  • 이벤트는 위쪽으로 전파된다. 첫 번째 매개변수로 e.stopPropagation()를 호출하여 방지할 수 있다.
  • 이벤트는 의도치 않은 기본 브라우저 동작을 유발할 수 있다. e.preventDefault()를 호출하여 방지할 수 있다.
  • 명시적으로 이벤트 핸들러 prop을 자식 핸들러에서 호출하는 것은 전파에 대한 좋은 대안이 될 수 있다.
profile
공유할 때 행복을 느끼는 프론트엔드 개발자

0개의 댓글