Edited at

ReactをES6で開発時のbindの問題

More than 3 years have passed since last update.


自己紹介

じゅんじゅんというニックネームで、関西を拠点に活動しているフロントエンドエンジニアです。

HAL大阪の2回生です👍 (2016.9.12現在)

よくstart up系イベントに行くので、大阪らへんの方は会いましょう!


bind問題とは

ReactをES6で書いた場合に、イベントハンドラでthisがundefinedとなりメソッドが実行できないという問題。

これはFacebookのReact公式にも書いていて

Reusable Components

このリンクの中盤すぎぐらいにES6 Classesと書いている欄。

No Autobindingと書いている。明示的にthisをバインドしてね!ってことらしいぞと。

ということで、解決策を具体的に書いていきたいと思います。


解決策たち

解決策的には


  1. constructor内に明示的にbind

  2. es6のアローファンクションを使う

  3. jsxコンポーネント内でbind

  4. stage-0でメソッドの定義をする

  5. es7のbindオペレータを使う

前半3つはすぐに導入することができますが、後半2つを使うには少しプラグインなどを入れる必要があります。


1. constructor内に明示的にbind

constructor(){

super()
this._hoge = this._hoge.bind(this);
}

_hoge(){
console.log("hoge");
}

この方法は、メソッドが多くなるにつれてthis祭りになるので、推奨はしないですが楽です()


2. es6のアローファンクションを使う

render(){

return(
<button onClick={(e)=>this._click(e)}>click me</button>
)
}

_click(){
console.log("click!")
}

この方法は、eventを渡す必要があるようなので(e)=>this._click(e)と書いています。


3. jsxコンポーネント内でbind

render(){

return(
<button onClick={this._click.bind(this)}>click me</button>
)
}

_click(){
console.log("click!")
}

これは、コンストラクタでthisのbindをしていない分jsxの方で書いとくぜ!って感じなんですかね。


4. stage-0でメソッドの定義をする

まず、この開発環境でstage-0が使えるようにしないといけません。

npm install babel-preset-stage-0

.babelrcにも記述しましょう


.babelrc

{

"presets": ["react", "es2015","stage-0"]
}

メソッドの書き方を変えましょう。

render(){

return(
<button onClick={this._click}>click me</button>
)
}

_click = () => {
console.log("click!")
}


5. es7のbindオペレータを使う

es7のbindオペレータを扱うためにbabelにプラグインとして

transform function bindを使います。

npm install babel-plugin-transform-function-bind

.babelrcにも記述しましょう


.babelrc

{

"presets": ["react", "es2015"],
"plugins": ["transform-function-bind"]
}

jsx内のthis._clickを書き換えます

render(){

return(
<button onClick={::this._click}>click me</button>
)
}

_click(){
console.log("click!")
}

この5つの方法以外の方法に、ReactのComponentを継承して自分でMyComponent見たいなものを作り、そのMYComponentのコンストラクタで_から始まるメソッドは全部thisでバインドする。みたいな書き方ができそう!って感じですが、今回はこの5つの方法で記事をまとめておきます。


最後に

個人的にReactをとても活用していて、最近やっとReactNativeを触り始めました。。

すごいですね...w

Googleのトレンド的にはAngular2とかがトレンドらしいので、また時間があれば噛んでみようかなと思ってます!

Twitter @konojunya