62
55

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Reactのイベント処理を理解しよう

Last updated at Posted at 2020-05-18

#目次

#概要
この記事は、Reactにおけるイベント処理の仕組みなどについてまとめています。主にReact初心者向けの内容となっています。
また私自身の備忘録としてイベントハンドラについても一覧としてまとめていますので、参考にしてみてください。

#イベント処理とは
イベント処理とは、ユーザが「クリック」や「入力」などの操作が発生したときにプログラム側が行う処理のことを言います。

#Reactのイベント処理
Reactでのイベント処理はDOM要素のイベント処理と非常に似ていますが、いくつかの特徴があります。

  • イベントはcamelCaseで名付ける(「onclick」ではなく「onClick」)
  • イベントハンドラには文字列ではなく関数を渡す

簡単な例を見てみましょう。特に<button>タブの中身に注目して見てください。
HTMLの場合

<html>
  <script>
    const buttonAlert = () => {
      alert('Clicked!');
    }
  </script>
  <body>
    <button onclick="buttonAlert()">Click me</button>
  </body>
</html>

Reactの場合

cnost App = () => {
  const buttonAlert = () => {
    alert('Clicked!');
  }

  return(
    <button onClick={buttonAlert}>Click me</button>
  );
}

<button>タブの中身がHTMLの場合とReactの場合とではわずかに違いますよね。
ReactでHTMLの場合のように記述してしまうとエラーとなりますので気をつけましょう。

ReactはJavaScriptのライブラリなので、イベント処理ではaddEventListenerを定義し、onClickなどのイベント属性内に記述することは変なのではと疑問に感じる方もいるかもしれません。しかしReact(JSX)では、イベント処理をonClick等のイベント属性に記述します。なぜこのような記述方法が可能なのかですが、JSXがレンダリングされるとき実際にはaddEventListenerに置換されるそうです。

上記の例のように状態などが無く、必ず同じ結果を返す場合は簡単に表現できます。
しかし状態によって処理に変更が生じる場合はどうなるでしょうか。

###メソッドのbind
はじめに例を見てみましょう。

src/Toggle.js
import React, { Component } from 'react';

class Toggle extends Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // ここに注目
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(state => ({
      isToggleOn: !state.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

export default Toggle;

これはボタンが押されるたびにONとOFFを切り替える機能を実装したプログラムです。
このとき、handleClick()メソッド内ではthisを使ってstateを参照していますが、thisconstructor内で使用されているのでhandleClick()メソッド内でも使用できるように関連付けてあげる必要があります。
このようにconstructor内でhandleClick()メソッドをbindすることでthisを使用できるようになります。

ただメソッドが多くなればなるほど、this.メソッド = this.メソッド.bind(this)のような宣言も増えますよね。それを回避するため、つまり明示的にbindを記述しない記述方法があります。

方法その1:ES6のアロー関数をJSX内で記述する方法
方法その2:Class Fields利用する方法

それぞれ見てみましょう。
方法その1

src/Toggle.js
import React, { Component } from 'react';

class Toggle extends Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};
    // bindを書かなくて良い
  }

  handleClick() {
    this.setState(state => ({
      isToggleOn: !state.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={() => this.handleClick()}>  {/* ここに注目 */}
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

export default Toggle;

方法その2

:src/Toggle.js
import React, { Component } from 'react';

class Toggle extends Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};
    // bindを書かなくて良い
  }

  handleClick = () => {  // ここに注目
    this.setState(state => ({
      isToggleOn: !state.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

export default Toggle;

bindのある場合、方法その1、その2いずれの場合も同じ結果になります。bindのない場合の方がすっきり見えますし、記述量も少なくて済むので良いですね。

方法その1、その2のような記述ができる理由については、現時点で調べてもよくわからなかったので詳しい方がいればコメントなどで教えてもらえるとありがたいです。私のようによくわからないという人は、そういう仕様と捉えておけば大丈夫かとおもいます。

注意点として方法その2の手法はTC39というJavaScript関係の委員会が提案している手法なのですが、現在Stage3で実験的に行っているそうなので環境的にできない場合もあるかと思います。Create React Appではデフォルトで利用できます。

(補足)
方法その2のようにClass Fieldsを利用すると、クラス構文でconstructorの宣言も省略することができます。

src/Toggle.js
import React, { Component } from 'react';

class Toggle extends Component {
  // ここに注目(this.state → state)
  state = {isToggleOn: true};

  handleClick = () => {
    this.setState(state => ({
      isToggleOn: !state.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

export default Toggle;

この場合propsはどう使うのか疑問に思うかもしれませんが、何も宣言せずに必要に応じてthis.propsも利用できます。

#イベントハンドラ一覧
Reactで用いることのできるイベントハンドラはJavaScriptのイベントハンドラに準拠しています。ではどのようなイベントハンドラがあるか見てみましょう。

イベントハンドラ 説明
onBlur / onFocus フォーカスが移動したとき
onChange フォームの入力値 / 選択が変更されたとき
onSelect / onSelectStart テキストが選択されたとき
onSubmit / onReset フォームの送信時 / リセット時
onAbort / onError 画像読み込み時の中断 / エラー
onLoad / onUnload ページの読み込み時 / 切り替え時
onClick / onDblClick クリック / ダブルクリックされたとき
onKeyPress / onKeyDown / onKeyUp キーの状態に応じる
onMouseOver / onMouseOut マウスを乗せたとき / 離したとき
onMouseDown / onMouseUp マウスでクリックしたとき
onMousemove マウスを動かしているとき

この辺りは覚えるというよりは、使いたいときに参照する程度にしておけばいいと思います。他にも色々あるので必要に応じて調べて使うようにしましょう。

#まとめ
今回はReactにおけるイベント処理とそのイベントハンドラについてまとめてみました。特に記述方法などの基礎的な部分に関してはしっかり抑えておきましょう。

  • イベントはcamelCaseで名付ける(「onclick」ではなく「onClick」)
  • イベントハンドラには文字列ではなく関数を渡す
  • bindは記述方法によって省略可能

#参考資料

62
55
1

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
62
55

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?