React.js

【React.js】チュートリアルのイベント処理について理解をまとめる

こんにちは、ともです。

現在Reactチュートリアルを進めながら勉強中でして、イベント処理について理解をまとめておきたいと思います。

イベント処理

関数コンポーネントとクラスコンポーネントでイベント処理のメソッドの記述方法が少し違いますので分けて書きたいと思います。

関数コンポーネントの場合

function HelloWorld() {
            function handleClick (e) {
                alert('Hello World')
            }

            return (
                <button onClick={handleClick}>
                        こんにちは
                </button>
            )
 }

JSXのイベントはキャメルケースで記述します。(onClick

そしてイベントハンドラを関数として渡します。({handleClick}

クラスコンポーネントの場合

class HelloWorld extends React.Component {
            constructor (props) {
                super(props)
            }

            handleClick () {
                alert('Hello World')
            }

            render () {
                return (
                    <button onClick={this.handleClick}>
                        こんにちは
                    </button>
                )
            }

}

クラスコンポーネントの場合は{this.handleClick}とします。クラス内に登録されたhandleClickメソッドを実行するためです。

イベントハンドラでthisを利用する場合の注意

次のようにイベントハンドラ内でthisキーワードを利用する場合には注意が必要です。

class HelloWorld extends React.Component {
            constructor (props) {
                super(props)
                this.state = {date: new Date()}
            }

            handleClick () {
                alert('Hello World' + this.state.data.toLocaleString())
            }

            render () {
                return (
                    <button onClick={this.handleClick}>
                        こんにちは
                    </button>
                )
            }

        }

上記のようなイベントを登録しました。しかしこのイベントは次のエラーが出ます。

Uncaught TypeError: Cannot read property ‘state’ of undefined

何故stateがundefinedになるのでしょうか?

JSX のコールバックにおける this の意味に注意しなければなりません。JavaScript では、クラスのメソッドはデフォルトではバインドされません。this.handleClick へのバインドを忘れて onClick に渡した場合、実際に関数が呼ばれた時に this は undefined となってしまいます。

つまり、JSXのコールバック関数であるhandleClickメソッドの中のthisがbindされていないためundefinedとなるようです。

これを回避するためにconstructorでbindメソッドを利用することで、handleClickメソッド内のthisの参照先をクラス自身に設定することができます。

class HelloWorld extends React.Component {
            constructor (props) {
                super(props)
                this.state = {date: new Date()}
                this.handleClick = this.handleClick.bind(this)// バインド
            }

            handleClick () {
                alert('Hello World' + this.state.date.toLocaleString())
            }

            render () {
                return (
                    <button onClick={this.handleClick}>
                        こんにちは
                    </button>
                )
            }

 }

これによりthisの参照先がクラス自身にバインドされました。

<button onClick={this.handleClick.bind(this)}>
                        こんにちは
</button>

JSXのインラン中でバンドすることも可能です。

まとめ

React.jsを利用してイベント処理を実装する方法についてまとめました。

バインドなどはJavaScriptのthisの参照先が文脈に依存すること、またJavaScriptのbindメソッドでthisの参照先を固定することを知っていれば理解が早いのではないでしょう。