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の提案中の構文になるので、変更または却下されている可能性があります。