2018/04/03更新

[フロントエンド] React.jsで、クラスのメソッドのthisを一括でバインドする

このエントリーをはてなブックマークに追加      

こんにちは、@yoheiMuneです。
今日はReactで、onClickなどで呼び出す関数のthisを、一括でクラスにバインドする方法を、ブログに書きたいと思います。



目次




何が問題か

ReactコンポーネントをES6のクラスで作成すると、onClickで呼び出すメソッドのthisundefinedになってしまいます。
import React, { Component } from 'react'

class MyComponent extends Component {

    onClick() {
        console.log(this)  // 「undefined」になる.
    }

    render() {
        return (
            <div onClick={this.onClick}>Click Me!!</div>
        );
    }
}
対処法としては以下のようにthisをバインドすれば良いのですが、毎回やるのは面倒です。
<div onClick={this.onClick.bind(this)}>Click Me!!</div>
それを、一括でやってしまおうというのが今回の内容です。



共通の親クラスを作成して、thisのバインドを行う

プロジェクト全体で利用する共通のベースコンポーネントを作成し、その中でthisのバインド処理を行います。各コンポーネントはこの親クラスを継承して作るようにすることで、thisのバインドを自動的に行います。

親クラスではconstructorの中で、自分自身の全てのメソッドについてthisのバインドを行います。
import { Component } from 'react'

/**
 * React.Componentの基底クラス.
 */
export default class AbstractComponent extends Component {

    constructor() {
        super(...arguments)
        this.autoBind()
    }

    // 自身のメソッドについて「this」のバインドを行う
    autoBind() {
      Object.getOwnPropertyNames(this.constructor.prototype)
        .filter(prop => typeof this[prop] === 'function')
        .forEach(method => {
          this[method] = this[method].bind(this);
        });
    }
}
そして、上記のクラスを継承して、各コンポーネントを作成します。
import React from 'react'
import AbstractComponent from './AbstractComponent'

class MyComponent extends AbstractComponent {  // <== 継承先を変更

    onClick() {
        console.log(this)  // MyComponentのインスタンスになってる!!
    }

    render() {
        return (
            <div onClick={this.onClick}>Click Me!!</div>
        );
    }
}
これで自動的にthisのバインドができました。



参考資料

onClickにおけるthisの扱いは、今回紹介した方法以外にもいくつか存在します。以下の公式ドキュメントをご参照ください。

Handling Events - React



最後に

僕は今回のやり方がしっくりきていますが、他にも色々と良い方法があるので、自分にあった(プロジェクトに合った)方法を選べるといいなと思います 。

最後になりますが本ブログでは、フロントエンド、Swift、PHP、Node.js、Linux、Python、Java、インフラ、Go言語、機械学習、などの技術トピックを発信をしていきます。「プログラミングで困ったその時の、解決の糸口に!」そんな目標でブログを書き続けています。ぜひ、本ブログのRSSTwitterをフォローして貰えたら嬉しいです ^ ^

最後までご覧頂きましてありがとうございました!





こんな記事もいかがですか?

[取り組み] フロントエンドでコーディングスピードをアップさせる6つの方法!と思って書いてたら30個も書いちゃった。
[フロントエンド] フロントエンドの入社試験99問!難しいですよ〜w。
[フロントエンド] Webページを表示するテストの際に、通信速度を3Gに制限して表示してみよう
[フロントエンド] スマホ実機でのデバッグ手段を増やす!Macのプロキシを利用して、通信内容を確認する。
[フロントエンド] Chrome 35 Beta の変更点。Touch制御、新しいJavaScript機能、プレフィックスなしのShadowDOM
[フロントエンド]複数アカウントでのテストには、Chromeのユーザー管理を使って、Cookieを切り替えると便利
[フロントエンド] Chrome36βが出た。変更点など。element.animate、HTML Imports、Object.observe、他。
RSS画像

もしご興味をお持ち頂けましたら、ぜひRSSへの登録をお願い致します。