Skip to main content

Command Palette

Search for a command to run...

React 이벤트 핸들러 네이밍은 어떤 방식으로 해야 할까 ?

Updated
4 min read

Moved my blog! 👉 https://www.youngminss-log.com

들어가면서

React 로 사이드 프로젝트를 다른 FE 개발자분들과 진행하면서 사전에 여러 컨벤션(커밋 컨벤션, 스타일링 컨벤션 등)을 정합니다. React 에서 이벤트 핸들러 메서드를 정의하고 바인딩하는 것 역시 그 중 하나여도 좋다고 생각합니다. 이번 포스팅에서는 React 커뮤니티에서 일반적으로 알려지고 있는 이벤트 핸들러 네이밍 컨벤션대해 정리해보겠습니다.


✅ 기본 네이밍

🔵 Function

  • handle* prefix 를 붙여서 작성합니다.
  • 예를 들어, handleClick

  • handle* 은 이벤트가 발생했을 때 어떤 것이 호출되는지를 의미합니다.

🔵 Props

  • on* prefix 를 붙여서 작성합니다.

  • 예를 들어, onClick

  • on* 은 어떠한 이벤트가 연결된다는 것을 의미합니다.


✅ 하나의 컴포넌트 관점에서

🔵 하나의 이벤트만 존재하는 경우

예를 들어, MyComponent 라는 컴포넌트 내부에서 button 요소에 onClick 이벤트가 하나만 존재한다는 전제하에 이벤트를 바인딩 한다면.

const MyComponent = () => {

    const handleClick = () => {
      console.log('button Clicked !!');
    }

    return <button type="button" onClick={handleClick}>...</button>  
}
  • 기본적으로 제공하는 onEvent 형식에 맞게 이벤트 핸들러 함수도 handleEvent 형식으로 사용합니다.

🔵 하나의 이벤트가 여러 개 존재하는 경우

이번에는 MyComponent 내부에 여러 개의 onClick 이벤트가 존재하는 경우를 봅시다.

const MyComponent = () => {

  const handleButtonOneClick = () => {
    console.log("button-one Click !!");
  }

  const handleButtonTwoClick = () => {
    console.log("button-two Click !!");
  }

  const handleButtonThreeClick = () => {
    console.log("button-three Click !!");
  }

  // 각각의 버튼은 다른 기능을 한다고 가정
    return (
    <>
          <button type="button" name="button-one" onClick={handleButtonOneClick}>...</button>
        <button type="button" name="button-two" onClick={handleButtonTwoClick}>...</button>
        <button type="button" name="button-three" onClick={handleButtonThreeClick}>...</button>
      </>
  )
}
  • 위 예시에서는 MyComponent 내부적으로는 button 요소가 3개가 존재하며 각각은 onClick 이벤트가 존재합니다.
  • 그렇다면, 위에서 언급한 onEvent - handleEvent 규칙을 지키기가 어렵습니다. (각 이벤트 발생 시, 다른 기능이 작동하기 때문)
  • 이런 경우는 handleComponentEvent 형식을 적용해볼 수 있습니다.
    • 위 예제에서는 각 button 요소에 name 속성으로, 서로 다른 컴포넌트라는 것을 가정했습니다.
    • 똑같은 button 요소에 대해 onClick 이벤트가 발생하지만, 각 클릭 이벤트에 바인딩된 이벤트 핸들러 함수는 각각 handleComponentEvent 규칙이 적용된 형태인 것을 확인할 수 있습니다.
      • button-one 버튼 -> onClick 이벤트 발생 시 -> handleButtonOneClick 이벤트 핸들러 함수 실행
      • button-two 버튼 -> onClick 이벤트 발생 시 -> handleButtonTwoClick 이벤트 핸들러 함수 실행
      • button-three 버튼 -> onClick 이벤트 발생 시 -> handleButtonThreeClick 이벤트 핸들러 함수 실행


✅ 상위 - 하위 컴포넌트 관계에서

// Counter 컴포넌트(상위)
const Counter = () => {
  const [count, setCount] = useState(0);

  // 실질적인 UI or 비즈니스 로직을 처리하는 이벤트 핸들러
  // 컴포넌트의 이벤트 관련된 파라미터들은 없고, 로직에 필요한 데이터만 받는다.
  const handleCountChange = (offset) => {
    setCount(count + offset)
  }

  return (
      <>
        <span>{count}</span>
        <BottonMinus onCountChange={handleCountChange} />
        <BottonPlus onCountChange={handleCountChange} />
      </>
  )
}

// ButtonPlus 컴포넌트(하위)
const ButtonPlus = ({ onCountChange }) => {

  // 특정 컴포넌트에 바인딩한 이벤트가 발생했을 때 수행되는 이벤트 핸들러
  // props 로 받을 UI or 비즈니스 로직을 담당하는 이벤트 핸들러들이 수행된다.
  const handlePlusButtonClick = (event) => {
       onCountChange(event.target.value);
  }

  return <button type="button" value={1} onClick={handlePlusButtonClick}>+</button>
}

// ButtonMinus 컴포넌트(하위)
const ButtonMinus = ({ onCountChange }) => {

  // 특정 컴포넌트에 바인딩한 이벤트가 발생했을 때 수행되는 이벤트 핸들러
  // props 로 받을 UI or 비즈니스 로직을 담당하는 이벤트 핸들러들이 수행된다.
  const handleMinusButtonClick = (event) => {
    onCountChange(event.target.value);
  }

  return <button type="button" value={-1} onClick={handleMinusButtonClick}>-</button>
}

정리하자면

  • props 로 전달받는 이벤트 핸들러는 onTargetEvent 형식으로 넘겨주고(상위 컴포넌트 입장) 받습니다(하위 컴포넌트 입장).
  • UI 나 비즈니스 로직을 수행할 이벤트 핸들러 함수의 경우 handleTargetEvent 형식으로 정의합니다.
  • 이벤트가 적용될 컴포넌트에 바인딩하는 이벤트 핸들러 함수의 경우 handleComponentEvent 형식으로 정의합니다.


✅ 주의할 점 - 기본으로 제공되는 핸들러 이름 사용 시(Using Built-in Handler Name)

const MyComponent = (props) => {
  return (
      <div {...props}>
      <button onClick={props.onClick}>Button</button>
      </div>
  )
}

위에 예제의 경우 다음과 같은 원치 않은 상황이 연출 될 수 있습니다.

  1. props 에는 onClick 이름(Built-in 이벤트 이름과 동일한)의 이벤트 핸들러가 있을 것이다.
  2. 개발자가 원했던 상황은 button 요소에만 props 로 전달한 onClick 이벤트 핸들러가 바인딩 되고 이벤트 발생 시 수행되길 원했을 것이다.
  3. 하지만, 모든 props 를 하나의 props 라는 parameter 에 담아서 주었기 때문에 div 요소에도 props 가 디스트럭처링 되면서 내부적으로 포함하고 있는 onClick 이벤트 핸들러 또한 적용될 것이다. (onClick={onClick} 형태로..)
  4. 결과적으로 button 을 클릭해서 button 의 onClick 이벤트가 발생했지만, 이벤트 버블링 현상 때문에 div 에 적용되어 있는 onClick 이벤트 또한 실행될 것 입니다.

따라서, 위와 같은 상황을 방지하기 위해서 props 에 담겨 내려올 내용 중 Built-in 이벤트와 이름이 같은 형태가 있을 경우, 이를 파라미터에서 분리하는 것이 일종의 사이드 이펙트를 막을 수 있는 방법입니다.

const MyComponent = ({ props, onClick ) => {
  return (
      <div {...props}>
      <button onClick={onClick}>Button</button>
      </div>
  )
}

참고 자료

  • https://stackoverflow.com/questions/60048249/what-is-the-right-name-of-event-handler-onclick-or-handleclick
  • https://velog.io/@dregonc/React-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%ED%95%B8%EB%93%A4%EB%9F%AC-%EB%84%A4%EC%9D%B4%EB%B0%8D
  • https://www.knowledgehut.com/blog/web-development/handling-react-events-guide
  • https://javascript.plainenglish.io/handy-naming-conventions-for-event-handler-functions-props-in-react-fc1cbb791364

React

Part 1 of 1

React 관련 학습 내용 및 고민의 흔적을 기록합니다.

More from this blog

[코어 자바스크립트] 02.실행 컨텍스트

실행 컨텍스트 실행 컨텍스트(execution context) 는 실행할 코드에 제공할 환경 정보들을 모아넣은 객체 ( JavaScript 가 왜 동적 언어인지 성격을 가장 잘 파악할 수 있는 개념 ) 동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성하고, 이를 콜 스택(call stack) 에 쌓아올렸다가, 스택 자료구조처럼 가장 위에 쌓여있는 컨텍스트와 관련 있는 코드들을 실행하는 식으로 전체 코드의 환...

Sep 25, 20228 min read

[JS 딥다이브] Iterable 객체

개요 JS 개발을 하다보면, Iterator, Array-like 같은 키워드를 볼 수 있고, 이런 자료형이어야 작동하는 프로세스들을 볼 수 있었을 것이다. JS ES6+ 에는 새로운 문법이나 Built-in Object 뿐만 아니라, protocols(표현법들)도 추가되었다. 이 protocol은 일정 규칙만 충족한다면, 어떠한 객체에서 의해서도 구현될 수 있다. 이러한 프로토콜은 2가지가 있다. Iterable protocol Iter...

Aug 27, 20229 min read

npm 과 yarn 은 뭐가 다를까 ?

개요 이전 시간에 npm 과 npx 에 대해 비교해봤다. 이번에는 npm과 yarn 에 대해 비교해본다. 평소에 JS 프로젝트를 진행하면서 npm 으로 패키지를 관리하는데, 뭔가 무겁다 정도의 느낌을 받을 정도로 개발을 해왔던, 조금이라도 그런 느낌을 받았다면 이 포스팅이 조금은 도움이 되리라. 본론 📍 npm 이전 시간에 "정의"에 대해서는 정리를 하였으니 간략하게. Node Package Manager(Javascript Node...

Aug 20, 20223 min read

Youngmin's Blog

11 posts