[React.js] #4 이벤트 다루기
오늘은 리액트에서 발생하는 다양한 이벤트를 어떻게 등록하고 관리하는지에 대하여 알아보는 시간을 갖도록 하겠습니다.
과연~? 리액트에서는 어떻게 이벤트를 처리할까요?
간단한 예제를 만들어보며 차근차근 확인해보도록 하겠습니다.
이벤트 등록하기
우선 간단하게 counter를 생성하고 버튼을 통해 count 값을 증가시켜주는 예제를 만들어 보겠습니다.
import React, { Component } from 'react'
class App extends Component {
render() {
return (
<div>
<p> count <p>
<button> BUTTON </button>
</div>
)
}
}
APP 컴포넌트는 카운트 값과 카운트를 증가시켜줄 버튼을 하나 가지게 됩니다.
이제 count를 관리할 수 있게 state를 선언해주고 버튼 클릭 시 이벤트를 발생시킬 수 있도록 함수를 생성해 보겠습니다.
import React, { Component } from 'react'
class App extends Component {
constructor(props) {
this.state = {
count: 0
}
}
handleCount(e) {
this.setState({
count: this.state.count+1
})
}
render() {
return (
<div>
<p> count is : {count} <p>
<button onClick={this.handleCount.bind(this)}> BUTTON </button>
</div>
)
}
}
여기서 살펴보아야 할 것은 "button" 태그의 "onclick" 그리고 "this.handleCount.bind(this)" 입니다.
1. 기존 html과 비교
기존 html에서 사용하던 button 태그의 onclick 이벤트 등록은 다음과 같습니다.
<button onclick="myFunction()">Click me</button>
React에서 사용하는 onclick 이벤트와 비교해 봅시다.
<button onClick={this.handleCount.bind(this)}> BUTTON </button>
리액트에서 이벤트 등록을 위해서는 onClick과 같이 카멜 케이스(camelCase) 형태로 호출하며 함수의 등록은 실행 형태가 아닌 함수 이름만 넣어 줍니다.
2. .bind(this)
위의 코드를 보면 "<button onClick={this.handleCount.bind(this)}>"를 통해 this를 바인드 해주고 있습니다.
왜? 이런 행동을 하는 걸까요?
이 과정은 컴포넌트에 이벤트 메소드를 바인딩하는 과정입니다. 이벤트 메소드 안에서 this를 사용하지 않는 경우는 상관없겠지만(?) this 객체에 접근해야하는 경우 우리가 원하는 this를 정상적으로 불러오지 못합니다. 이벤트 메소드를 컴포넌트에 바인딩 해주지 않으면 이벤트 메소드의 this는 "window 객체" 혹은 "undefined"를 가리키고 있습니다.
더구나 이벤트 메소드 부분을 다시 살펴보면
handleCount = (e) => {
this.setState({
count: this.state.count+1
})
}
컴포넌트의 "setState"를 통해 state 값을 변경해줘야 하는데 컴포넌트에 바인딩이 되어 있지 않으면? 당연히 에러가 발생하게 됩니다.
사실, 컴포넌트에 이벤트 메소드를 바인딩하거나 손쉽게 사용하는 방법에는 몇 가지가 더 있습니다.
1. 이벤트 등록 시 바로 바인딩하는 방식
<button onClick={this.handleCount.bind(this)}> BUTTON </button>
2. 생성자 함수 내부에서 바인딩 하는 방식
class App extends Component {
constructor(props) {
super(props)
this.state = {
count: 0,
}
this.countHandle = this.countHandle.bind(this)
}
(...)
}
3. arrow function을 통한 방식
class App extends Component {
(...)
handleCount = (e) => {
this.setState({
count: this.state.count+1
})
}
render() {
return (
<div>
<p> count is : {count} <p>
<button onClick={this.handleCount}> BUTTON </button>
</div>
)
}
}
개인적으로는 arrow function으로 선언하여 사용하는게 제일 깔끔하고 이쁜 것 같아요 ㅎㅎㅎ
** 주의 사항 **
이벤트 등록 아래와 같이 메소드를 등록하면 어떻게 될까요?
<button onClick={this.countHandle()}> BUTTON </button>
위와 같이 함수를 등록하게 된다면 "초기 랜더링" -> "메소드 실행" -> "setState()" -> "또 랜더링" -> "또 함수 호출" -> ..... 와 같은 지옥에 빠질 수 있으니 사용에 유의해 주세요.
이벤트 함수에 인자 전달하기
이벤트 핸들러에 파라메터를 전달하는 방식입니다.
<button onClick={(e) => this.countHandle(id, e)}> BUTTON </button>
<button onClick={this.countHandle.bind(this, id)}> BUTTON </button>
두 경우 모두 React 이벤트를 나타내는 e 인자가 ID 뒤에 두 번째 인자로 전달됩니다. 화살표 함수를 사용하면 명시적으로 인자를 전달해야 하지만 bind를 사용할 경우 추가 인자가 자동으로 전달됩니다.
이렇게 이번 포스팅에서는 이벤트를 다루는 방법에 대해서 알아보았습니다. 설명이 부정확하거나 누락된 부분이 존재할 수 있습니다.
좀 더 정확한 정보를 드리기 위해 항상 노력하고 있으니 양해 부탁드립니다 ( _ _ )
탕빠이!