흰 스타렉스에서 내가 내리지

이벤트 핸들러 props 로 전달하기, 이벤트 전파, 이벤트 방지 본문

React

이벤트 핸들러 props 로 전달하기, 이벤트 전파, 이벤트 방지

주씨. 2024. 5. 19. 00:41
728x90

이벤트 핸들러를 속성으로 전달하기

자주 사용되는 시나리오 중 하나는 상위 컴포넌트에서 자식의 이벤트 핸들러를 지정하는 것입니다.

예를 들어 버튼을 고려해 보겠습니다.

Button 컴포넌트를 사용하는 위치에 따라 다른 기능을 실행할 수 있습니다.

예를 들어 한 컴포넌트에서는 영화 재생을 실행하고 다른 컴포넌트에서는 이미지를 업로드할 수 있습니다.

 

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

function PlayButton({ movieName }) {
  function handlePlayClick() {
    alert(`Playing ${movieName}!`);
  }

  return (
    <Button onClick={handlePlayClick}>
      Play "{movieName}"
    </Button>
  );
}

function UploadButton() {
  return (
    <Button onClick={() => alert('Uploading!')}>
      Upload Image
    </Button>
  );
}

export default function Toolbar() {
  return (
    <div>
      <PlayButton movieName="Kiki's Delivery Service" />
      <UploadButton />
    </div>
  );
}

 

마지막으로 Button 컴포넌트는 onClick이라는 prop을 허용합니다.

디자인 시스템을 사용하는 경우 버튼과 같은 컴포넌트에는 스타일링만 포함되고 동작은 지정되지 않는 것이 일반적입니다.

대신 PlayButton과 UploadButton과 같은 컴포넌트에서 이벤트 핸들러를 전달합니다.

 

 

이벤트 핸들러 속성의 이름 정하기

직접 만드는 컴포넌트에서는 이벤트 핸들러 속성의 이름을 원하는 대로 지정할 수 있습니다.

관례적으로 이벤트 핸들러 속성은 on으로 시작하고 대문자로 시작하는 형식으로 작성해야 합니다.

예를 들어 Button 컴포넌트의 onClick prop은 onSmash로 지정할 수 있습니다.

 

export default function App() {
  return (
    <Toolbar
      onPlayMovie={() => alert('Playing!')}
      onUploadImage={() => alert('Uploading!')}
    />
  );
}

function Toolbar({ onPlayMovie, onUploadImage }) {
  return (
    <div>
      <Button onClick={onPlayMovie}>
        Play Movie
      </Button>
      <Button onClick={onUploadImage}>
        Upload Image
      </Button>
    </div>
  );
}

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

App 컴포넌트는 Toolbar가 onPlayMovie 또는 onUploadImage를 어떻게 사용하는지 알 필요가 없습니다. 이것은 Toolbar의 구현 세부사항입니다.

onPlayMovie과 같은 앱 특정 상호작용에 대한 props 이름을 사용하면 나중에 사용 방식을 변경할 수 있는 유연성을 제공합니다.

 

 

이벤트 전파

이벤트 핸들러는 해당 컴포넌트의 자식 요소에서도 이벤트를 캐치합니다.

이벤트가 "버블링" 또는 "전파"되어 트리 상위로 이동한다고 말합니다.

 <div>는 두 개의 버튼을 포함하고 있습니다. 

<div>와 각 버튼에는 자체적인 onClick 핸들러가 있습니다. 버튼을 클릭하면 어떤 핸들러가 실행될 것 같나요?

 

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>
  );
}

 

버튼을 클릭하면 해당 버튼의 onClick이 먼저 실행되고 그 다음에 부모 <div>의 onClick이 실행됩니다. 따라서 두 개의 메시지가 표시됩니다.

툴바 자체를 클릭하면 부모 <div>의 onClick만 실행됩니다.

 

 

모든 이벤트는 React에서 전파되며, 그 중에서도 onScroll은 연결된 JSX 태그에서만 작동합니다.

 

 

전파 중지

이벤트 핸들러는 이벤트 객체를 유일한 인수로 받습니다.

관례적으로 이벤트 객체의 변수명은 e로 사용됩니다. 이 객체를 사용하여 이벤트에 대한 정보를 읽을 수 있습니다.

 

이벤트 전파를 중지할 수도 있습니다. 이벤트가 상위 컴포넌트로 전달되지 않도록 하려면 e.stopPropagation()을 호출해야 합니다. Button 컴포넌트에서 이렇게 하고 있습니다.

 

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()을 호출하여 이벤트가 더 이상 전파되지 않도록 합니다.
    • onClick 함수를 호출합니다. 이 함수는 Toolbar 컴포넌트에서 전달된 prop입니다.
  3. Toolbar 컴포넌트에서 정의된 이 함수는 버튼의 알림을 표시합니다.
  4. 전파가 중지되었기 때문에 부모 <div>의 onClick 핸들러는 실행되지 않습니다.

 

기본 동작 방지

일부 브라우저 이벤트에는 기본 동작이 연결되어 있습니다.

예를 들어 <form> 내에서 버튼을 클릭할 때 발생하는 제출(submit) 이벤트는 기본적으로 전체 페이지를 다시 로드합니다.

 

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