[React] 이벤트 핸들링과 바인딩

sunaaa·2021년 3월 20일

🎯 문제 상황 : 함수 호출과 render

얼마 전 이미지 카드 클릭하면 alert창을 뜨게 만드는 기능을 구현하던 중, render 문제를 겪은 적이 있었다. 처음에 이벤트를 구현하고자 아래와 같은 코드를 썼었다.

// 샘플 코드
<button onClick=
{alert(`어글리 몬스터${id}${name}님을 채용하시겠습니까?`)}>
Pick</button>

그러자 클릭 이벤트를 적용 후 특정 카드 이미지를 클릭할 때 alert가 실행되는 것이 아니라 컴포넌트가 render 되며 카드 이미지 개수(12개)만큼 alert가 12번 실행되고, 카드 이미지를 클릭했을 땐 아무런 현상도 일어나지 않았다.

공부하다보니 그 이유를 알게 되었다.

  • onClickalert 함수 호출을 바로 하는 경우, 컴포넌트를 render될 때 함수 호출의 결과가 onClick에 바인딩 된다.
  • 그에 따라 컴포넌트가 render될 때 alert가 실행이 된다.
  • 결과값인 undefined(함수는 return 값이 없을 때 undefined를 반환한다)가 onClick에 바인딩 되기 때문에 클릭 했을 때 아무런 결과도 일어나지 않는 것이었다.

당시 이 문제를 해결할 때, onClick에 함수 호출이 아닌 함수를 정의해 해결했었다. 정확한 문제발생의 원인과 해결된 이유는 모르고 우연히 이것저것 시도해보다 때려맞춘 느낌이었는데 이유를 알게 되어 속시원하다.

💎 새로 알게 된 것

React는 이벤트가 발생했을 때 표현식에 정의되어 있는 함수를 자동으로 호출한다. 때문에 함수 호출을 이벤트에 적용 하면 함수 호출의 결과가 이벤트에 적용된다. 그러므로 함수 호출이 아닌 함수 자체를 적용해야 한다.

💎 일반 함수 this VS 화살표 함수 this

당시 대희님이 지나가다 내 코드를 보고는 함수 선언식을 화살표 함수로 고쳐주셨는데, 그 이유도 당시엔 그저 가독성 때문인 줄 알았다.

// 샘플 코드
// arrow function
<button onClick=
{alert(() => `어글리 몬스터${id}${name}님을 채용하시겠습니까?`)}>
Pick</button>

// function declarations
<button onClick=
{alert(function() {`어글리 몬스터${id}${name}님을 채용하시겠습니까?`)}}>
Pick</button>

그런데 일반 함수 선언식의 경우 함수 본문에서 this를 사용할 때 문제가 될 수 있어 가능하면 화살표 함수로 사용할 것을 권장한다고 한다.

  • 💌 this는 함수가 어디서 호출되는지에 따라 결정되기 때문에 this 바인딩을 주의해야 한다. 클래스의 임의 메소드가 특정 HTML 요소의 이벤트로 등록되는 과정에서 메소드와 this의 관계가 끊어지게 되기 때문이다.

  • 따라서 this를 컴포넌트 자신으로 가르키게 하기 위해 메소드를 this와 바인딩하는 작업이 필요하다. 메소드 바인딩은 생성자 메소드에서 하는 것이 정석이다. 새 메소드를 만들 때마다 constructor 도 수정해야하기 때문이다.

  • 하지만 클래스형 컴포넌트에서 public class fields 문법을 사용하여 화살표 함수로 메소드를 구현하면, 좀 더 편하게 작성할 수 있다. 화살표 함수this는 부모 함수의 this를 상속받는데 JS에서 클래스는 함수로 구현되어 있기 때문에 this는 컴포넌트 자신이 되므로 bind(this)를 하지 않아도 된다.

  • 이 문법은 아직 ECMAScript 표준으로 받아들여지지 않은 실험적인 문법이라, babel-plugin-transform-class-properties을 써서 바벨을 설정해주어야 하는데 Create-React-App 으로 만든 프로젝트는 이 문법이 기본적으로 설정되어 있으므로 별다른 설정 없이 사용가능하다.

➡ 일반 함수와 화살표 함수의 this 차이.
일반 함수는 전역 컨텍스트에서 실행될 때 this를 정의한다. 화살표 함수this를 정의하지 않는다. 함수의 내부함수, 콜백함수에 사용되는 thiswindow이다. 화살표 함수는 자신을 포함하는 외부 scope에서 this를 계승받는다는 말이다. 즉, 화살표 함수는 자신만의 this를 생성하지 않는다. (Lexical this)

참고자료

profile
Be Playful Front-end Developer

2개의 댓글

comment-user-thumbnail
2021년 3월 21일

오오 새로운 사실..감사합니다!! 😍😍

1개의 답글