본문 바로가기
Language/React

[React 공식 Doc 가이드 #7] Handling events

by ocwokocw 2021. 2. 11.

- 이 글은 React 공식 홈페이지 Docs v16.8.3 (https://reactjs.org/docs) 에 기반하여 작성한 글입니다.

- React 에서의 Event

React element 에서의 event 사용법은 DOM element 에서 사용하는 법과 비슷하지만 구문적으로 약간의 차이가 있다.

React 에서는 소문자 대신 camelCase를 사용한다.

 

스트링으로 함수를 쓰지 않고 JSX 문법으로 event handler 함수를 넘긴다. 예를들어 HTML 에서는 아래와 같이 쓰는 button click 예제가

React 에서는 아래와 같이 된다.

또 하나 다른점은 보통 기본동작을 막기 위해 preventDefault 대신 onclick 에서 return false 를 쓰기도 하는데, React 에서는 명시적으로 preventDefault 라고 써야한다.(기본동작을 막기 위해 return false 를 사용할 수 없다.)

 

예를들어 아래와 같이 쓰던 문법이

React 에서는 아래와 같이 된다.

여기서 clickAction의 e 는 event를 나타내는데 React 에서는 이러한 event는 W3C spec 에 따라서 정의 하였다. (크로스 브라우징 호환성에 대해서 신경쓰지 않아도 된다.)

 

React 를 사용할 때에는 DOM 이 생성된 후에 listner 를 추가하기 위해서 addEventListener 를 호출할 필요없이 초기 rendering 시에 listener 를 사용하면 된다.

 

ES6 class 를 이용해서 component 를 정의할 때에는 일반적으로 event handler 가 class의 method 가 된다. 아래의 "ON" 과 "OFF" 가 toggle 되는 Toggle component 를 살펴보자.

여태까지 배워온것을 토대로 toggle 버튼을 만드는건 크게 어렵지 않을 것이다. 여기서 한 가지 주의할점이 있다. JSX callback 에서 this 가 가리키는 context 에 주의 해야 한다. JavaScript 에서 class method 는 자동으로 this 를 class 로 바인딩 시켜주지 않는다. 만약에 this.toggleAction 에 class 의 this 를 바인딩 하는걸 까먹으면 실제 함수가 호출됐을때 this 는 undefined 여서 동작하지 않는다.

 

이런 특성은 React 를 사용해서 그런게 아니라 JavaScript 의 특성이므로 조심하자. 일반적으로 () 없이 method 를 참조한다면(onClick={this.toggleAction}) method를 바인딩 해야 하지 않는지 생각해 봐야 한다.

 

설명을 들으면 알 것 같긴한데 그래도 눈으로 직접 보는게 좋겠다 constructor 와 호출되는 함수에 debugger; 를 걸고 개발자도구를 켜자. (아래 코드는 this.toggleAction = this.toggleAction.bind(this)를 주석처리 하고 실행 시켰다.)

위는 constructor 생성자에서 debugger 를 걸었고, this 를 조사식으로 써서 이 생성자 안에서 this 의 의미를 살펴본 모습이다. toggleAction도 정의가 되어있고, props 나 state 도 보인다.

버튼을 누르면 toggleAction이 호출되는건 binding을 해주나 안해주나 호출이 되긴 한다. 그런데 this 를 조사해보면 undefined가 나오며 우리가 참조해야할 state, 즉 this.state 를 조사해 보려고 하면 undefined 된 state 속성을 읽을 수 없다면서 에러가 난다.

 

this 를 바인딩 하기 귀찮다면 2가지 방법이 있다. (그거 바인딩 하는게 뭐가 귀찮냐고 할 수도 있지만 실제 Project 는 예자와 달리 코드량이 압살이고 실제로 매우 귀찮다면서 불평하는 사람들이 많다.)

 

첫번째 방법은 public class field syntax 를 사용하는 것이다. 

다소 생소한 문법처럼 보인다. 심지어 공식 가이드에서도 실험적인 문법이라고 소개하고 있다. 실험적인 문법이라도 사용하는게 뭐가 문제냐고 할 수도 있지만, 실제로 SI 를 뛰어보면 개발자부터 거부감을 보이는 개발자도 있고, 인수인계 받는 쪽에서는 문제가 생기면 책임소재를 따지기도 한다. 실제로 Project 내에서 쓰고 싶다면 열린마음의 사람들과 일 할때 쓰도록 하자.

 

이 문법은 npx 를 이용해서 따라했다면(공식 Doc 에서 Create React App, 이 가이드 대로 따라했다면) 기본적으로 사용가능한 문법이다.

 

이 방법이 싫다면 좀 더 익숙한 방법이 있다. callback 에서 arrow function 을 사용하는 방법이다.

ES6 에서 arrow function 을 소개할 때 this 의 context 가 달라진다는 것은 javascript 에 조금이라도 관심이 있는 사람이면 알 것이다. 

 

이 문법의 문제점은 LogginButton 이 rendering 될 때 마다 다른 callback 이 만들어진다는 것이다. 대부분의 경우에는 괜찮지만 만약 이 callback 이 하위 component 에서 props 로 참조될 때, 이런 component 들에서 추가적으로 re-rendering 이 일어날 수도 있다.

 

공식 문서에서는 이런 문제를 피하기 위해서 constructor 에서 this 를 binding 하거나, 첫번째 방법을 사용하는 것을 추천하고 있다.


- Passing Arguments to Event Handlers

Component 를 반복적으로 처리하는 loop (일반적으로 Project 에서 table 에서 tr 을 반복적으로 그리는 경우) 에서 event handler 에 추가적인 parameter(예를들면 rowId) 를 넘기길 원하는 경우가 생길수도 있다.

아래 두 예제를 살펴보자.

위의 두 예제, arrow function을 사용한 첫번째 예제와 Function.prototype.bind를 이용한 두번째 예제는 문법적으로 동치이다.

위의 두 경우 모두 id 뒤에 2번째 인자로 넘어가는 e argument 는 React event를 나타낸다. arrow function 의 경우에는 e argument를 명시적으로 넘겨야 하지만 bind 를 이용하면 추가적인 argument 가 자동적으로 맵핑된다.

댓글