LoginSignup
2
4

More than 5 years have passed since last update.

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

Last updated at Posted at 2019-02-02

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のスコープは奥が深いというかクセがある。。

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4