이 블로그는 광고 클릭 수익으로 운영됩니다!
괜찮으시다면 광고 차단을 풀어주세요 ㅠㅠ

게시글

강좌4 - React - 2년 전 등록 / 일 년 전 수정

컴포넌트 이벤트 연결(바인딩)

조회수:
0
이 블로그는 광고 클릭 수익으로 운영됩니다!
괜찮으시다면 광고 차단을 풀어주세요 ㅠㅠ
이 블로그는 광고 클릭 수익으로 운영됩니다!
괜찮으시다면 광고 차단을 풀어주세요 ㅠㅠ

안녕하세요. 이번 시간에는 React 컴포넌트에 이벤트를 연결(바인딩)하는 방법을 알아보겠습니다.

import React, { Component, PropTypes } from 'react';

class Basic extends Component {
  constructor(...args) {
    super(...args);
    this.state = {
      hidden: false,
    };
    this.onClickButton = this.onClickButton.bind(this);
  }

  onClickButton() {
    this.setState(() => ({ hidden: true }));
  }

  render() {
    return (
      <div>
        <span>저는 {this.props.lang} 전문 {this.props.name}입니다!</span>
        {!this.state.hidden && <span>{this.props.birth}년에 태어났습니다.</span>}
        <button onClick={this.onClickButton}>숨기기</button>
      </div>
    );
  }
}

Basic.propTypes = {
  name: PropTypes.string.isRequired,
  birth: PropTypes.number.isRequired,
  lang: PropTypes.string,
};

Basic.defaultProps = {
  lang: 'Javascript',
};

export default Basic;

지난 시간에 봤던 컴포넌트죠? 그런데 한 가지 달라진 부분이 있습니다. button의 onClick 속성을 따로 onClickButton 메소드로 분리했는데요. 그게 전부가 아닙니다. ES2015 class에서만 있는 특별한 현상이 있습니다.

바로 constructor 안에 this.onClickButton = this.onClickButton.bind(this); 라는 이상한 코드가 들어있습니다. 이 부분이 이벤트를 바인드(bind)하는 부분입니다. 저는 처음에 도대체 this.onClickButton에 this를 왜 bind하는 건지 이해가 되지 않았습니다. 그런데 함수의 원리를 알고 보면 이해가 됩니다.

onClickButton() {
  this.setState(() => ({ hidden: true }));
}

이 부분은 ES5 코드로 보면

onClickButton: function() {
  this.setState(() => ({ hidden: true }));
}

인데요. 문제점은 this.onClickButton = this.onClickButton.bind(this); 를 하지 않으면 render 메소드에서 this.onClickButton 함수를 호출했을 때 함수의 this가 windowundefined가 되어버립니다. 따라서 window나 undefined에는 setState 메소드가 없기 때문에 this.setState 호출 시 에러가 발생하죠.

왜 this가 window나 undefined가 되는지 알기 위해서는, this.onClickButton이 실행되는 환경을 잘 보아야 합니다. this.onClickButton이 실행되는 순간 (function() { this.setState(() => ({ hidden: true })); })(); 가 실행되는데, 이때의 this는 window입니다. 이 함수 자체만 놓고 보면, 자바스크립트 엔진은 this가 뭔지 모르기 때문에 그냥 최상위와 연결시켜버립니다.

이해가 잘 안 되나요? 그렇다면 이런 복잡한 생각 없이 쉽게 하는 방법이 있습니다. ES2015의 새로운 기능인 arrow function을 사용하면 됩니다. arrow function은 this를 자동으로 bind해주기 때문에 간단합니다. 대신 babel-preset-stage-2가 필요합니다. 위의 컴포넌트는 다음과 같아집니다.

import React, { Component, PropTypes } from 'react';

export default class Basic extends Component {
  static propTypes = {
    name: PropTypes.string.isRequired,
    birth: PropTypes.number.isRequired,
    lang: PropTypes.string,
  };

  static defaultProps = {
    lang: 'Javascript',
  };

  state = {
    hidden: false,
  };

  onClickButton = () => {
    this.setState(() => ({ hidden: true }));
  }

  render() {
    return (
      <div>
        <span>저는 {this.props.lang} 전문 {this.props.name}입니다!</span>
        {!this.state.hidden && <span>{this.props.birth}년에 태어났습니다.</span>}
        <button onClick={this.onClickButton}>숨기기</button>
      </div>
    );
  }
}

static 키워드 덕분에 Basic 컴포넌트와 따로 분리되어 있던 defaultProps와 propTypes가 안으로 들어갔습니다. 또 constructor 안에 있던 state는 바깥으로 나왔고요. onClickButton 메소드까지 arrow function으로 만들면 이제 constructor가 필요없어집니다. 복잡한게 싫다 싶으면 이 방법을 사용합니다. 앞으로도 이 방법을 사용하겠습니다.

다음 시간에는 컨텍스트(context) 참조(Reference)에 대해 알아보겠습니다!

투표로 게시글에 관해 피드백을 해주시면 많은 도움이 됩니다. 오류가 있다면 어떤 부분에 오류가 있는지도 알려주세요! 잘못된 정보가 퍼져나가지 않도록 도와주세요.
Copyright © 2016- 무단 전재 및 재배포 금지

댓글

1개의 댓글이 있습니다.
일 년 전
"되늕" 오타 있네요.