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 = () => {...} のようにES6の書き方にしてあげるという方法もあります。

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に精通されてる方は間違えないとは思いますが、ES6に慣れてなければこんな間違いもしてしまいます。

上記のように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してあげるか、ES6のアロー関数の書き方にしてあげると想定通りの動作をしてくれるようになります。

補足: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>;
  }
}

それでは、よきJavaScript Lifeを。

SNSでもご購読できます。

コメントを残す

*