React에서의 바인딩(binding) 방법들

기존의 react에서의 React.createClass() 메소드를 사용하여 컴포넌트를 생성하면 이 메소드가 자동으로 mixin 과 autobinding을 다뤄주어 바인딩을 할 필요가 없었습니다.

그런데 최신 JS의 객체 지향성 클래스라는 기능을 가지게 되어 리액트도 이를 지원하게 되어 조금 더 바닐라 자바스크립트와 가깝게 되었죠. 그래서 최근 리액트 프로젝트들은 컴포넌트를 es6 class를 사용하는 추세입니다.

JS object에 달린 메소드의 this는 그 메소드가 포함된 object를 가르키게 됩니다:

var obj = {  
prop: 'Hello',
sayHello: function() {
console.log( this.prop );
}
};

obj.sayHello(); // Logs "Hello"

그런데 sayHello() 의 호출을 다른 방식으로 해보면:

var reference = obj.sayHello;  
reference(); // logs "undefined"

undefined가 출력되는데요, 그 이유는 바로 reference를 sayHello에 저장할때 obj 와의 관계를 상실하기 때문입니다. 여기에서는 메소드로써가 아니라 함수로써 호출하는 것입니다.

그럼 위의 문제를 어떻게 해결해야 할까요? 바로 이렇게 합니다:

var obj = {  
prop: 'Hello',
sayHello: function() {
console.log(this.prop);
}
};

var newFunction = obj.sayHello.bind(obj);
newFunction(); // logs "Hello"

bind() 를 통해 새로운 함수 newFunctionthis 가 언제나 obj 임을 가르키게 됩니다. newFunction 을 호출할 때 이 함수의 thisbind의 첫 인자가 되는 것이죠.

리액트에서는 위의 바인딩이 적용될 때가 꽤 자주 있습니다. 하지만 언제나 바인딩을 해야할 필요는 없죠. 오직 메소드를 다른 메소드에서 사용할 때만 바인딩하면 됩니다.

아래에서:

class Home extends React.Component {

update() {
this.setState({
newStuff: true
});
}

render() {
return <div
onClick={ this.update }
/>;
}

}

render() 메소드가 update를 부를 때 여기서는 메소드를 호출한 것이 아니라 함수를 호출한것이죠. this 가 무엇을 가리키는지 정확히 정의되지 않았죠. 그래서 바인딩을 통해 관계를 설정해줘야 합니다.

리액트에서는 아래와 같은 방법들로 바인딩할 수 있습니다.

방법 1: render() 안에 바인딩

render() {  
return <div
onClick={ this.update.bind( this ) }
/>
}

방법2: constructor() 안에 바인딩

class Home extends React.Component {

constructor() {
super()
this.update = this.update.bind(this);
}

방법3: 오토바인딩 데코레이터 사용

import autobind from 'autobind-decorator'

class Home extends React.Component {
@autobind
update() {
...
}

방법4: 그냥 createClass() 쓰기

reference:

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.