(JSX) メソッド内でthisを正しく参照する

(JSX) メソッド内でthisを正しく参照する:

React.Componentのメソッドを使う際にthisが正しく参照できないことがあった。その原因と対処法を記す。動かせるコードはこちら


問題

Click Me!という文字列をクリックした時にThanksと文字列が切り替わるようなコンポーネントを実装したい。
demo.gif

ここで次のようなコードにすると、クリックしても文字が切り替わらない。

class Clickable extends React.Component { 
  constructor(props) { 
    super(props); 
    this.state = { msg: "Click Me!"}; 
  }; 
  render () { 
     return <h1 onClick={this.handleClick}>{ this.state.msg }</h1>; 
  }; 
  handleClick () { this.setState({ msg: "Thanks!"}); }; 
} 
 
ReactDOM.render( 
  <Clickable/>, 
  document.getElementById('mount') 
); 
原因はメソッドhandleClickを定義した時に、thisのスコープがメソッド内のものに置き換わってしまい、クラス内のスコープのthisを参照することが出来ないためだ。

正しく動作させるための対処法を以下に書いていく。


対処法①:コンストラクタで束縛する

最初の対処法はクラスのコンストラクタ内でクラスのスコープでのthisをメソッドに束縛させる方法だ。

class Clickable extends React.Component { 
  constructor(props) { 
    super(props); 
    this.state = { msg: "Click Me!"}; 
    // 対処法①  コンストラクタ内でhandleClickを束縛する 
    this.handleClick = this.handleClick.bind(this); 
  }; 
  ... 
} 
この方法はうまくいくが、束縛はコンストラクタ内で行う必要があるため、コンストラクタを省略することが出来なくなるという欠点がある。


対処法②:クロージャを使う

2番目の対処法はメソッド呼び出しの時にクロージャを使うことだ。renderが実行された時、クロージャによってクラスのthisが束縛されるので、メソッド内で正しく参照を行うことが出来るようになる。

render () { 
     return <h1 onClick={() => this.handleClick()}>{ this.state.msg }</h1>; 
  }; 
この書き方ではコンストラクタ内で束縛する必要がなくなるため、コンストラクタが不必要な場合は省略することが出来る。


対処方③:アロー関数を使う

最後の対処法はメソッドhandlwClickの定義にアロー関数表記を使うことだ。アロー関数は変数のリスコープを行わないので、元々のthisをメソッド内部でそのまま参照することが出来る。JavaScriptでは関数は第1級のオブジェクトであるため、アロー関数をクラスのメンバ変数として登録している形となっている。

handleClick = () =>  { this.setState({ msg: "Thanks!"}); }; 
この書き方でもコンストラクタ内で束縛を行う必要はないので、コードが短くなる。


まとめ

メソッド内でクラスのthisを参照する方法を3つ紹介した。

どうもJSのスコープは奥が深いというかクセがある。。

コメント

このブログの人気の投稿

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-04-30 23:37:32 RSSフィード2021-04-30 23:00 分まとめ(42件)

投稿時間:2023-02-05 02:09:04 RSSフィード2023-02-05 02:00 分まとめ(9件)