そもそも、該当のコードはstage 3のClass Fieldsを用いた記法です。ECMAScriptの正式な仕様としては認められていません。stage 3ですので、このまま採用される可能性はありますが、変更される可能性もあることに留意すべきです。
さて、話は置いといて、ECMAScript 2017の仕様でそのまま書いた場合、handleClick
は普通のメソッドとして定義することになると思います。
JavaScript
1import React from 'react';
2
3class CountUp extends React.Component {
4 constructor(props) {
5 super(props);
6 this.state = { count: 0 };
7 }
8
9 handleClick(e) {
10 this.setState({ count: this.state.count + 1 });
11 }
12
13 render() {
14 return(
15 <button onClick={this.handleClick}>
16 {this.state.count}
17 </button>
18 );
19 }
20}
もちろん、これは正常に動きません。なぜなら、onClickにはhandleClick
という関数だけを渡しているため、this
が何であるかという情報が欠如されるからです。クリックによってコールバックで呼び出されるときにthis
はこのオブジェクトのことではなくなり、this.setState()
の呼出しに失敗します。
それを解決する手段の一つとして、{(e) => this.handleClick(e)}
があったのです。こちらは=>
によってthis
が束縛されるため、this
がこのオブジェクトであるところの関数というものをonClickに渡します。ですので、コールバックでもthis
が何か別のものになるのを防ぎます。他の解決方法として{this.handleClick.bind(this)}
とする方法や、コンストラクタでthis.handleClick = this.handleClick.bind(this);
としておくという方法があります。そして、第4の方法として、該当コードであるClass Fieldsを用いた記法が(まだ正式では無いが)できるようになったと言うことです。
つまり、イベントのコールバックされる関数のthis
の問題に対する解決方法について、次のいずれかを行えば良いとなります。
- アロー関数
=>
で囲って渡す。{(e) => this.handleClick(e)}
bind(this)
して渡す。{this.handleClick.bind(this)}
- コンストラクタで
bind(this)
しておく。this.handleClick = this.handleClick.bind(this);
- Class Fieldsでアロー関数を使う。
handleClick = (e) => {...};
これはどれか一つだけで十分であり、複数を採用することは意味がありません。どれがいいかは一長一短になります。1.は毎回アロー関数を作るコストがかかります。2.も毎回新しい関数オブジェクトを作っています。3.はメソッド定義とコンストラクタにそのメソッドに対する情報が分散しています。4.はまだstage 3であり、仕様が変わる恐れがあります。
参考: Handling Events - React
[蛇足]
私のお勧めは第5の邪法であるCoffeeScript(2.0.0以上)を使うことです。
CoffeeScript
1import React from 'react'
2
3class CountUp extends React.Component
4 constructor: (props) ->
5 super(props)
6 @state = count: 0
7
8 handleClick: (e) =>
9 this.setState count: @state.count + 1
10
11 render: ->
12 <button onClick={@handleClick}>
13 {@state.count}
14 </button>
JSX記法にも対応したCoffeeScriptに死角は無い!
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/11/24 04:00 編集
2017/11/24 04:03
2017/11/24 04:06
2017/11/24 04:19 編集
2017/11/24 13:19
2017/11/24 15:07 編集