v19.2Latest

이벤트에 응답하기

React를 사용하면 JSX에이벤트 핸들러를 추가할 수 있습니다. 이벤트 핸들러는 클릭, 마우스 오버, 폼 입력 필드 포커스 등과 같은 상호작용에 응답하여 트리거될 사용자 정의 함수입니다.

배울 내용
  • 이벤트 핸들러를 작성하는 다양한 방법
  • 부모 컴포넌트에서 이벤트 처리 로직을 전달하는 방법
  • 이벤트가 전파되는 방식과 이를 중지하는 방법

이벤트 핸들러 추가하기

이벤트 핸들러를 추가하려면 먼저 함수를 정의한 다음 적절한 JSX 태그에prop으로 전달합니다. 예를 들어, 아직 아무 동작도 하지 않는 버튼이 있습니다:

사용자가 클릭할 때 메시지를 표시하도록 만들려면 다음 세 단계를 따르세요:

  1. Button컴포넌트내부에 handleClick이라는 함수를 선언합니다.
  2. 해당 함수 내부에 로직을 구현합니다 (메시지를 표시하려면alert를 사용하세요).
  3. JSX의<button>onClick={handleClick}를 추가합니다.

handleClick함수를 정의한 다음 이를prop으로 전달하여<button>에 연결했습니다.handleClick이벤트 핸들러입니다. 이벤트 핸들러 함수는 다음과 같습니다:

  • 일반적으로 컴포넌트내부에정의됩니다.
  • 이름은 handle로 시작하고 그 뒤에 이벤트 이름을 붙이는 것이 관례입니다.

관례상 이벤트 핸들러의 이름은 handle뒤에 이벤트 이름을 붙이는 것이 일반적입니다.onClick={handleClick},onMouseEnter={handleMouseEnter}등을 자주 볼 수 있습니다.

또는 JSX 안에 인라인으로 이벤트 핸들러를 정의할 수도 있습니다:

또는, 더 간결하게 화살표 함수를 사용할 수 있습니다:

이 모든 스타일은 동등합니다. 인라인 이벤트 핸들러는 짧은 함수에 편리합니다.

주의사항

이벤트 핸들러에 전달되는 함수는 호출되는 것이 아니라 전달되어야 합니다. 예를 들어:

함수 전달 (올바름)함수 호출 (잘못됨)
<button onClick={handleClick}><button onClick={handleClick()}>

차이는 미묘합니다. 첫 번째 예시에서는handleClick 함수가 onClick이벤트 핸들러로 전달됩니다. 이는 React에게 이 함수를 기억해두었다가 사용자가 버튼을 클릭할 때만 호출하라고 지시하는 것입니다.

두 번째 예시에서는handleClick()끝에 있는()가 함수를 즉시실행하게 하여, 클릭 없이도렌더링 중에 실행됩니다. 이는 JSX { 및 }안의 JavaScript가 바로 실행되기 때문입니다.

코드를 인라인으로 작성할 때도 동일한 문제가 다른 방식으로 나타납니다:

함수 전달 (올바름)함수 호출 (잘못됨)
<button onClick={() => alert('...')}><button onClick={alert('...')}>

이렇게 인라인 코드를 전달하면 클릭 시 실행되지 않고, 컴포넌트가 렌더링될 때마다 실행됩니다:

이벤트 핸들러를 인라인으로 정의하려면 다음과 같이 익명 함수로 감싸세요:

이렇게 하면 매 렌더링마다 코드를 실행하는 대신, 나중에 호출될 함수를 생성합니다.

두 경우 모두 전달하고자 하는 것은 함수입니다:

  • <button onClick={handleClick}>handleClick함수를 전달합니다.
  • <button onClick={() => alert('...')}>() => alert('...')함수를 전달합니다.

화살표 함수에 대해 자세히 알아보세요.

이벤트 핸들러에서 props 읽기

이벤트 핸들러는 컴포넌트 내부에 선언되므로 컴포넌트의 props에 접근할 수 있습니다. 다음은 클릭 시messageprop을 알림으로 표시하는 버튼입니다:

이렇게 하면 두 버튼이 서로 다른 메시지를 표시할 수 있습니다. 전달되는 메시지를 변경해 보세요.

이벤트 핸들러를 props로 전달하기

종종 부모 컴포넌트가 자식의 이벤트 핸들러를 지정하길 원할 것입니다. 버튼을 생각해 보세요:Button컴포넌트를 사용하는 위치에 따라, 다른 함수를 실행하고 싶을 수 있습니다—예를 들어 하나는 영화를 재생하고 다른 하나는 이미지를 업로드하는 함수일 수 있습니다.

이를 위해, 컴포넌트가 부모로부터 받은 prop을 다음과 같이 이벤트 핸들러로 전달하세요:

여기서,Toolbar 컴포넌트는 PlayButtonUploadButton을 렌더링합니다:

  • PlayButton은 내부의ButtononClickprop으로handlePlayClick을 전달합니다.
  • UploadButton은 내부의ButtononClickprop으로')을 전달합니다.

마지막으로, 여러분의Button 컴포넌트는 onClick이라는 prop을 받습니다. 이 prop을 내장된 브라우저<button>onClick={onClick}로 직접 전달합니다. 이는 React에게 클릭 시 전달된 함수를 호출하라고 지시합니다.

만약 디자인 시스템을 사용한다면, 버튼과 같은 컴포넌트가 스타일링을 포함하지만 동작은 지정하지 않는 것이 일반적입니다. 대신,PlayButtonUploadButton과 같은 컴포넌트가 이벤트 핸들러를 아래로 전달하게 됩니다.

이벤트 핸들러 prop 이름 지정하기

및 와 같은 내장 컴포넌트는 인 만 지원합니다

관례상, 이벤트 핸들러 prop의 이름은 으로 시작하고 대문자가 뒤따라야 합니다.

예를 들어, 컴포넌트의 prop은 라고 불릴 수도 있습니다:

이 예시에서 는 브라우저의 (소문자)가 여전히 이라는 prop을 필요로 하지만, 사용자 정의 컴포넌트가 받는 prop의 이름은 여러분에게 달려 있음을 보여줍니다!

컴포넌트가 여러 상호작용을 지원할 때, 앱 특화 개념에 맞게 이벤트 핸들러 prop의 이름을 지정할 수 있습니다. 예를 들어, 이 컴포넌트는 및 이벤트 핸들러를 받습니다:

여기서 App 컴포넌트가 무엇을ToolbaronPlayMovieonUploadImage로 할지 알 필요가 없다는 점에 주목하세요. 그것은Toolbar의 구현 세부사항입니다. 여기서Toolbar는 이들을 onClick핸들러로 자신의Button에 전달하지만, 나중에 키보드 단축키로도 트리거할 수 있습니다.onPlayMovie와 같이 앱 특화 상호작용에 따라 props를 명명하면 나중에 사용 방식을 변경할 수 있는 유연성을 얻습니다.

참고

이벤트 핸들러에 적절한 HTML 태그를 사용해야 합니다. 예를 들어, 클릭을 처리하려면<button onClick={handleClick}>를 사용하고<div onClick={handleClick}>는 사용하지 마세요. 실제 브라우저<button>을 사용하면 키보드 탐색과 같은 내장 브라우저 동작을 활성화합니다. 버튼의 기본 브라우저 스타일링이 마음에 들지 않고 링크나 다른 UI 요소처럼 보이게 만들고 싶다면 CSS로 이를 달성할 수 있습니다.접근성 있는 마크업 작성에 대해 자세히 알아보세요.

이벤트 전파

이벤트 핸들러는 컴포넌트가 가진 모든 자식에서 발생하는 이벤트도 포착합니다. 우리는 이벤트가 트리를 따라 "버블링"되거나 "전파"된다고 말합니다: 이벤트가 발생한 곳에서 시작하여 트리 위로 올라갑니다.

<div>는 두 개의 버튼을 포함합니다.<div>각 버튼 모두 자신만의onClick핸들러를 가지고 있습니다. 버튼을 클릭할 때 어떤 핸들러가 실행될 것이라고 생각하시나요?

버튼 중 하나를 클릭하면, 해당 버튼의onClick이 먼저 실행되고, 그 다음 부모<div>onClick이 실행됩니다. 따라서 두 개의 메시지가 나타납니다. 툴바 자체를 클릭하면 부모<div>onClick만 실행됩니다.

주의사항

React에서 onScrollonScroll을 제외한 모든 이벤트는 전파됩니다. 은 연결된 JSX 태그에서만 작동합니다.

전파 중지하기

이벤트 핸들러는 유일한 인수로이벤트 객체를 받습니다. 관례상, 이 객체는 보통 "event"를 의미하는e라고 부릅니다. 이 객체를 사용하여 이벤트에 대한 정보를 읽을 수 있습니다.

이 이벤트 객체를 통해 전파를 중지할 수도 있습니다. 이벤트가 부모 컴포넌트에 도달하는 것을 방지하려면, 아래e.stopPropagation()을 호출해야 합니다:Button컴포넌트가 하는 것처럼

버튼을 클릭하면:

  1. React는onClick핸들러를 호출합니다. 이 핸들러는<button>에 전달되었습니다.
  2. 그 핸들러는 Button컴포넌트에 정의되어 있으며, 다음 작업을 수행합니다:
    • 이벤트가 더 이상 버블링되지 않도록e.stopPropagation()를 호출합니다.
    • 부모 onClick컴포넌트에서 전달된 prop인Toolbar함수를 호출합니다.
  3. 그 함수는 Toolbar컴포넌트에 정의되어 있으며, 버튼 자체의 경고를 표시합니다.
  4. 전파가 중단되었으므로, 부모<div>onClick 핸들러는 실행되지 않습니다.

결과적으로e.stopPropagation()덕분에, 버튼을 클릭하면 이제 두 개의 경고(<button>과 부모 툴바 <button>에서) 대신 단 하나의 경고(<div>에서)만 표시됩니다. 버튼을 클릭하는 것은 주변 툴바를 클릭하는 것과 다르므로, 이 UI에서는 전파를 중단하는 것이 합리적입니다.

Deep Dive
캡처 단계 이벤트

전파 대신 핸들러 전달하기

이 클릭 핸들러가 코드 한 줄을 실행한후에부모가 전달한onClickprop을 호출하는 방식을 주목하세요:

부모의 onClick이벤트 핸들러를 호출하기 전에 이 핸들러에 더 많은 코드를 추가할 수도 있습니다. 이 패턴은 전파에 대한대안을 제공합니다. 자식 컴포넌트가 이벤트를 처리하면서도 부모 컴포넌트가 추가적인 동작을 지정할 수 있게 합니다. 전파와 달리 자동이 아닙니다. 하지만 이 패턴의 장점은 특정 이벤트의 결과로 실행되는 전체 코드 흐름을 명확하게 따라갈 수 있다는 점입니다.

전파에 의존하고 어떤 핸들러가 실행되는지 왜 실행되는지 추적하기 어렵다면, 이 방법을 대신 사용해 보세요.

기본 동작 방지하기

일부 브라우저 이벤트에는 연결된 기본 동작이 있습니다. 예를 들어,<form>내부의 버튼을 클릭할 때 발생하는 submit 이벤트는 기본적으로 전체 페이지를 새로 고침합니다:

이벤트 객체에서e.preventDefault()를 호출하여 이를 방지할 수 있습니다:

e.stopPropagation()e.preventDefault()를 혼동하지 마세요. 둘 다 유용하지만 서로 관련이 없습니다:

  • e.stopPropagation()는 상위 태그에 연결된 이벤트 핸들러가 실행되는 것을 멈춥니다.
  • e.preventDefault()는 해당 기능을 가진 몇몇 이벤트에 대한 브라우저의 기본 동작을 방지합니다.

이벤트 핸들러는 부수 효과를 가질 수 있나요?

물론입니다! 이벤트 핸들러는 부수 효과를 처리하기에 가장 적합한 곳입니다.

렌더링 함수와 달리, 이벤트 핸들러는순수할필요가 없습니다. 따라서 무언가를변경하기에 좋은 곳입니다. 예를 들어, 타이핑에 대한 응답으로 입력값을 변경하거나, 버튼 클릭에 대한 응답으로 목록을 변경하는 것이죠. 그러나 정보를 변경하려면 먼저 그것을 저장할 방법이 필요합니다. React에서는 이를상태(state), 즉 컴포넌트의 메모리를 사용하여 수행합니다. 다음 페이지에서 이에 대해 모두 배우게 될 것입니다.

요약

  • 함수를 <button>와 같은 요소의 prop으로 전달하여 이벤트를 처리할 수 있습니다.
  • 이벤트 핸들러는 호출이 아니라 전달onClick={handleClick}해야 합니다.onClick={handleClick()}가 아닙니다.
  • 이벤트 핸들러 함수를 별도로 정의하거나 인라인으로 정의할 수 있습니다.
  • 이벤트 핸들러는 컴포넌트 내부에 정의되므로 props에 접근할 수 있습니다.
  • 부모 컴포넌트에서 이벤트 핸들러를 선언하고 자식 컴포넌트에 prop으로 전달할 수 있습니다.
  • 애플리케이션에 특화된 이름으로 자신만의 이벤트 핸들러 prop을 정의할 수 있습니다.
  • 이벤트는 위쪽으로 전파됩니다. 첫 번째 인수에서e.stopPropagation()를 호출하여 이를 방지할 수 있습니다.
  • 이벤트에는 원치 않는 브라우저 기본 동작이 있을 수 있습니다. 첫 번째 인수에서e.preventDefault()를 호출하여 이를 방지할 수 있습니다.
  • 자식 핸들러에서 이벤트 핸들러 prop을 명시적으로 호출하는 것은 전파에 대한 좋은 대안입니다.

도전 과제를 시도해 보세요

Challenge 1 of 2:이벤트 핸들러 수정하기 #

이 버튼을 클릭하면 페이지 배경이 흰색과 검은색 사이에서 전환되어야 합니다. 하지만 클릭해도 아무 일도 일어나지 않습니다. 문제를 해결하세요. (handleClick 내부의 로직은 걱정하지 마세요—그 부분은 괜찮습니다.)