본문 바로가기
목차
[노트장] 적으며 정리해 보는 이론/리액트문서

[리액트문서보기][상호작용성 더하기] 이벤트에 응답하기

by 졸린부엉이 2024. 3. 25.

학습내용

  • 이벤트 핸들러를 작성하는 여러가지 방법
  • 이벤트 핸들링 로직을 부모 컴포넌트에서 전달하는 방법
  • 이벤트가 전파되는 방식와 이를 멈추는 방법

 


 

 이벤트 핸드러 추가하기  

이벤트 핸들러 추가를 위해서는 먼저 함수를 정의하고 이를 적절한 JSX 태그에 props 형태로 전달 해야 합니다.

// 함수형
export default function Button() {
  function handleClick() { // Button 외부에 있어도됨(참조할 값 유무에 따라)
    alert('You clicked me!');
  }

  return (
    <button onClick={handleClick}>
      Click me
    </button>
  );
}


// 인라인 형
<button onClick={function handleClick() {
  alert('You clicked me!');
}}>

 

 

이벤트 핸들러 함수는 다음 특징을 가집니다

- 주로 컴포넌트 내부에서 정의됩니다.
- handle로 시작하고 그 뒤에 이벤트명을 붙인 함수명을 가집니다.

관습적으로 handle로 시작하여 이벤트명을 이어 붙인 이벤트 핸들러 명명법이 일반적입니다. onClick={handleClick}, onMouseEnter={handleMouseEnter}와 같은 경우를 자주 볼 수 있을 것입니다

 

 

[+주의]

다음과 같이 인라인 함수를 전달하면 버튼을 클릭할 때마다 실행되는 것이 아니라 컴포넌트가 렌더링 될 때마다 실행될 것입니다.
// 이 alert는 클릭 시 실행되지 않고 컴포넌트가 렌더링 된 시점에 실행됩니다!
// 랜더링 때 마다 실행
<button onClick={alert('You clicked me!')}>​

만약 이벤트 핸들러를 인라인으로 정의하고자 한다면, 아래와 같이 익명 함수로 감싸면 됩니다.
<button onClick={() => alert('You clicked me!')}>​

 

 

 

 


 

 

 이벤트 전파  

 

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

 

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

 

 

[+주의]
부여된 JSX 태그 내에서만 실행되는 onScroll 을 제외한 React 내의 모든 이벤트는 전파됩니다.

 

 

단계별 이벤트 캡처

드물게 전파가 중단된 상황일지라도 자식 컴포넌트의 모든 이벤트를 캡처해 확인해야 할 수 있습니다. 일례로, 분석을 위해 전파 로직에 상관 없이 모든 클릭 이벤트를 기록하고 싶을 수 있습니다. 이를 위해서는 이벤트명 마지막에 Capture를 추가하면 됩니다.

// Capture 예시

function App () {
	return <>
    	// Capture 추가
    	1.<div onClickCapture={() => { console.log(app!!) }}>
        <Toolbar/>
    </>
}


export default function Toolbar() {
  return (
    2.<div className="Toolbar" onClick={() => {
        e.stopPropagation(); // 전파가 부모 컴포넌트에 닿지 못하도록
        alert('You clicked on the toolbar!');
    }}>
      3.<Button onClick={() => {
        e.stopPropagation(); // 전파가 부모 컴포넌트에 닿지 못하도록
        alert('Playing!')}
      }>
        Play Movie
      </Button>
    4.<Button onClick={() => alert('Uploading!')}>
        Upload Image
      </Button>
    </div>
  );
}

//Capture를 뒤에 추가 하면, 실행이 됩니다.
// 3번 버튼을 클릭히면, 1,2 출력 후 멈춤
// 4번 버튼을 클릭하면  1,4,2 출력

이벤트 캡처는 라우터나 분석을 위한 코드에 유용할 수 있지만 일반 애플리케이션 코드에서는 잘 사용하지 않을 가능성이 높습니다.

 

 

 


 

 

이벤트 핸들러가 사이드 이펙트를 가질수도 있나요? 

네, 이벤트 핸들러는 사이드 이펙트를 가질 수 있습니다.

 

이벤트 핸들러는 사용자의 동작에 반응하여 발생하는 것으로, 이를 통해 상태를 변경하거나 외부와 상호작용할 수 있습니다. 예를 들어, 입력 필드에서 텍스트를 입력하거나 버튼을 클릭하는 등의 동작에 따라 상태를 변경하거나 외부 리소스에 요청을 보내는 등의 작업을 수행할 수 있습니다.

 

따라서 이벤트 핸들러는 순수성의 규칙을 준수할 필요가 없습니다. 사이드 이펙트를 포함하는 것이 이벤트 핸들러의 주된 목적이기 때문입니다. 그러나 이러한 사이드 이펙트가 예측 가능하고 관리 가능하도록 주의하여야 합니다.

React에서는 이벤트 핸들러를 사용하여 사용자 동작에 반응하고 컴포넌트의 상태를 업데이트하는 데 주로 활용됩니다. 상태를 업데이트하기 위해서는 setState나 다른 상태 관리 방법을 사용하여 상태를 변경해야 합니다.

 

 

 


 

 

 

◼ 요약 

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

 

 

 

 

[참고]
https://www.youtube.com/watch?v=rKJvwh20ogE&list=PLjQV3hketAJkh6BEl0n4PDS_2fBd0cS9v&index=15

https://ko.react.dev/learn/responding-to-events#event-propagation