우선 리액트에서 핸들러 이벤트를 바인딩 해주어야 하는 것은 순전히 자바스크립트 상의 이유이며, 리액트 작동 방식과는 관련이 없다는 점을 짚어야 한다.
EventBind
컴포넌트를 만들고 App
으로 가져와서 렌더한다.
import React, { Component } from 'react'
class EventBind extends Component {
constructor(props) {
super(props)
this.state = {
message: 'Hello' // 기본 설정
}
}
render() {
return (
<div>
<div>{this.state.message}</div> // Hello 출력
<button>Click</button> // 클릭 버튼
</div>
)
}
}
export default EventBind
버튼을 클릭하면 Hello
가 Goodbye
로 바뀌도록 해보자.
// bad
class EventBind extends Component {
constructor(props) {
super(props)
this.state = {
message: 'Hello'
}
}
handleClick() {
this.setState({
message: 'Goodbye!' // 클릭하면 Goodbye 바뀌는 함수
})
}
render() {
return (
<div>
<div>{this.state.message}</div>
<button onClick={this.handleClick}>Click</button>
</div> // 온클릭 이벤트와 함수 연결
)
}
}
이렇게 입력하면, Cannot read property 'setState' of undefined
에러가 발생한다.
handleClick() {
// this.setState({
// message: 'Goodbye!'
// })
console.log(this)
}
브라우저 콘솔에서 버튼을 클릭하고 확인해보면 this
의 값으로 undefined
가 로그되고 있다. this
를 바인딩 해주어야 하는 이유다.
클래스 컴포넌트 기준
render() {
return (
<div>
<div>{this.state.message}</div>
<button
onClick={this.handleClick.bind(this)}>
Click
</button>
</div>
)
}
스테이트 변경으로 렌더가 갱신될 때마다 이벤트 핸들러도 갱신된다. 앱 규모가 크면 문제가 될 수 있다.
화살표 함수의 본문 안에서 이벤트 핸들러 함수를 호출한다.
render() {
return (
<div>
<div>{this.state.message}</div>
<button
onClick={() => this.handleClick()}>
Click
</button>
</div>
)
}
화살표 함수 내 single statement 이므로return
이 생략되어 있는 점을 기억한다. 이벤트 핸들러 함수를 호출하여 value
를 리턴하고 있다. 이 방법 또한 일부 경우 성능 문제를 일으킬 수 있다.
리액트 공식 문서에서 소개하는 방법으로, 가장 널리 쓰인다.
class EventBind extends Component {
constructor(props) {
super(props)
this.state = {
message: 'Hello'
}
this.handleClick = this.handleClick.bind(this); // 바인딩
}
handleClick() {
this.setState({
message: 'Goodbye!'
})
console.log(this) // EventBind
}
render() {
return (
<div>
<div>{this.state.message}</div>
<button
onClick={this.handleClick}> // 이벤트와 함수 연결
Click
</button>
</div>
)
}
}
처음에 constructor
가 호출될 때 한번의 바인딩만 일어나므로 효율적이다.
마찬가지로 리액트 공식 문서에서 권고하는 방법이지만 아직까지는 완전하지 않은 부분이 있다고 알려진다.
handleClick = () => { // 화살표 함수로 작성한다.
this.setState({
message: 'Goodbye!'
})
}
render() {
return (
<div>
<div>{this.state.message}</div>
<button
onClick={this.handleClick}>
Click
</button>
</div>
)
}