React Componentでのthis.functionの動作を調べる

プログラミング

Reactを触っていると普通のJavaScriptとの動作の違いに戸惑うことがあります。

例えば、

import React, { Component } from 'react';
 
export default class App extends Component {
  onPress() {
    console.log(this);
  }
 
  render() {
    return <button onClick={this.onPress}>click</button>;
  }
}

このコードでonPress()内のthisがどのような表示をするかわかるでしょうか。
実は、この答えは undefined になります。

この答えを聞いて「なんで?」と思われた方は、この続きを読み進めてみてください。

React Component内の関数について

上記の場合では、onPress内のthisはundefinedになってしまいます。

では、どのようにすればいいのかと言うと、buttonタグのonClick={this.onPress}の部分をonClick={this.onPress.bind(this)}のようにしてonPress内でthisを認識させてあげる方法があります。

他にもonPressをonPress() {...}ではなく、onPress = () => {...}のようにECMAScriptの書き方にしてあげるという方法もあります。

Reactにはこのようにメソッドを呼び出す際には少し注意が必要な場合があるのです。

間違いパターン①

export default class App extends Component {
  onPress = () => {...}
 
  render() {
    return <button onClick={this.onPress()}>click</button>;
  }
}

今回はonClickの中身がthis.onPress()というようになっています。この場合はrenderされる度にonPressが実行されるようになります。

onClickメソッドの中にはメソッドの呼び出しをするのではなく、メソッド自体を渡してあげるようにしましょう。

今回のケースでは、this.onPress()this.onPressとしてあげるのが正解です。

間違いパターン②

export default class App extends Component {
  onPress = () => {...}
 
  render() {
    return <button onClick={() => this.onPress}>click</button>;
  }
}

JavaScriptに精通されてる方は間違えないとは思いますが、ECMAScriptに慣れてなければこんな間違いもしてしまいます。

上記のようにonClickの中身で関数の実行を定義するケースでは、this.onPressでは、メソッド本体を渡しているだけなので呼び出しが行われません。

こちらのケースではthis.onPress()で渡してあげるのが正解になります。

間違いパターン③

export default class App extends Component {
  onPress() {...}
 
  render() {
    return <button onClick={this.onPress}>click</button>;
  }
}

本記事の最初に紹介したコードと同じパターンですね。

こちらのケースでは、onPress()内でthisを呼び出そうと思うとundefinedで返ってきます。classにおいてメソッドの中でさらに関数呼び出しをするとundefinedになるのと同じなのかなと思っています。

render の中でonPress()を呼び出しているからだと思いますが調べきれていません、、、。

上記でも書いていますが、onPress に this をbindしてあげるか、ECMAScriptのアロー関数の書き方にしてあげると想定通りの動作をしてくれるようになります。

補足:methodに引数を渡す場合

勘のいい方は気づかれたかもしれませんが、上記では onClick の中身をthis.onPressのようにメソッド本体を渡す方法と() => this.onPress()と関数を呼び出す方法の2種類を紹介しています。

基本的にどちらでもいいですが、引数を渡すケースだけは少し考えなければなりません。

というのも、this.onPressのようにメソッド本体を渡す方法では引数を渡すことができないためです。

したがって、引数を渡す場合は下記のように書いてあげるようにしましょう。

export default class App extends Component {
  onPress = (something) => {...}
 
  render() {
    return <button onClick={() => this.onPress(this.props.something)}>click</button>;
  }
}
タイトルとURLをコピーしました