React Componentでthisがundefinedになる問題の解決策
プログラミング#Inside-ShouldBee#React#ES6

suin
・
2015年7月5日 投稿

最近、ShouldBeeのUIをReact.jsで作り始めています。
Babelを使ってES6のclass構文でReactのComponentを作っているのですが、どうもコールバックのメソッドでthis
がundefined
になってしまいます。
例えば、下のJSはボタンのコンポーネントで、クリックしたときに、onClick
メソッドが呼ばれます。onClick
メソッドの中で、this
を参照していますが、undefined
になります。
jsx
import React from "react";
export default class Button extends React.Component {
onClick() {
console.log(this); // undefined
}
render() {
return (
<button onClick={this.onClick}>Button</button>
);
}
}
ここでは、この問題を解決する方法を紹介したいと思います。解決方法は4つあります。
> 解決策1__colon__ XMLの中でbind解決策1: XMLの中でbind
1つ目はXMLの中でthis
をbindする方法です。
jsx
render() {
return (
<button onClick={this.onClick.bind(this)}>Button</button>
);
}
> 解決策2__colon__ Autobindingを使う解決策2: Autobindingを使う
React v0.13.0 Beta 1 | Reactで紹介されている方法です。コンストラクタでバインドするというものです。
jsx
export default class Button extends React.Component {
constructor() {
super();
this.onClick = this.onClick.bind(this);
}
onClick() {
console.log(this);
}
render() {
return (
<button onClick={this.onClick}>Button</button>
);
}
}
> 解決策3__colon__ __at__autobindデコレーターを使う解決策3: @autobind
デコレーターを使う
ES7で提案されている機能のデコレーターを使う方法です。andreypopp/autobind-decoratorというライブラリが公開されていて、これをnpmでインストールしておくとメソッドに対して、@autobind
デコレーターを使えるようになります。
jsx
export default class Button extends React.Component {
@autobind
onClick() {
console.log(this);
}
render() {
return (
<button onClick={this.onClick}>Button</button>
);
}
}
> 解決策4__colon__ Function Bind Syntaxを使う解決策4: Function Bind Syntaxを使う
Function Bind SyntaxもまたES7で提案されている機能のひとつで、メソッドの頭に::
をつけるとthis
がbindできるというものです。::foo
はfoo.bind(this)
のシュガーシンタクスになります。React Componentの場合はXMLの中でonClick={::this.onClick}
のように使うことができます。
jsx
export default class Button extends React.Component {
onClick() {
console.log(this);
}
render() {
return (
<button onClick={::this.onClick}>Button</button>
);
}
}
以上が解決策の紹介になります。なお、解決策3,4については、記事執筆時点でES7の提案中の構文になるので、変更または却下されている可能性があります。