리액트 이벤트 핸들러 바인딩

jh22j9·2020년 8월 29일

우선 리액트에서 핸들러 이벤트를 바인딩 해주어야 하는 것은 순전히 자바스크립트 상의 이유이며, 리액트 작동 방식과는 관련이 없다는 점을 짚어야 한다.

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

![https://velog.velcdn.com/images%2Fbitalkil%2Fpost%2Ff4b0b89a-5339-4d83-b0ca-2668ca07fe95%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202020-06-02%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.55.36.png%5D(https%3A%2F%2Fimages.velog.io%2Fimages%2Fbitalkil%2Fpost%2Ff4b0b89a-5339-4d83-b0ca-2668ca07fe95%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202020-06-02%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.55.36.png)

버튼을 클릭하면 HelloGoodbye로 바뀌도록 해보자.

// 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를 바인딩 해주어야 하는 이유다.

다양한 이벤트 핸들러 함수 바인딩 방법

클래스 컴포넌트 기준

1. render() 안에서 바인딩

render() {
    return (
      <div>
        <div>{this.state.message}</div>
        <button
          onClick={this.handleClick.bind(this)}>
          Click
          </button>
      </div>
    )
  }

스테이트 변경으로 렌더가 갱신될 때마다 이벤트 핸들러도 갱신된다. 앱 규모가 크면 문제가 될 수 있다.

2. 화살표 함수로 이벤트 핸들러 함수를 호출

화살표 함수의 본문 안에서 이벤트 핸들러 함수를 호출한다.

render() {
    return (
      <div>
        <div>{this.state.message}</div>
        <button
          onClick={() => this.handleClick()}>
          Click
          </button>
      </div>
    )
  }

화살표 함수 내 single statement 이므로return이 생략되어 있는 점을 기억한다. 이벤트 핸들러 함수를 호출하여 value를 리턴하고 있다. 이 방법 또한 일부 경우 성능 문제를 일으킬 수 있다.

3. Constructor 내에서 바인딩

리액트 공식 문서에서 소개하는 방법으로, 가장 널리 쓰인다.

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가 호출될 때 한번의 바인딩만 일어나므로 효율적이다.

4. 이벤트 핸들러 함수를 화살표 함수로 작성

마찬가지로 리액트 공식 문서에서 권고하는 방법이지만 아직까지는 완전하지 않은 부분이 있다고 알려진다.

handleClick = () => { // 화살표 함수로 작성한다. 
    this.setState({
      message: 'Goodbye!'
    })
  }

  render() {
    return (
      <div>
        <div>{this.state.message}</div>
        <button
          onClick={this.handleClick}>
          Click
          </button>
      </div>
    )
  }

🔗 ReactJS Tutorial - 14 - Binding Event Handlers

0개의 댓글