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

jh22j9·2020년 8월 29일
0

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

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개의 댓글