イベントへの応答

React では、JSX にイベントハンドラを追加できます。イベントハンドラとはあなた自身で書く関数であり、クリック、ホバー、フォーム入力へのフォーカスといったユーザインタラクションに応答してトリガされます。

このページで学ぶこと

  • イベントハンドラを記述するさまざまな方法
  • 親コンポーネントからイベント処理ロジックを渡す方法
  • イベントの伝播のしかたとそれを停止する方法

イベントハンドラの追加

イベントハンドラを追加するには、まず関数を定義し、適切な JSX タグに props の一部として渡します。例として、以下にまだ何もしないボタンを示します。

export default function Button() {
  return (
    <button>
      I don't do anything
    </button>
  );
}

ユーザがクリックするとメッセージが表示されるようにするには、以下の 3 つの手順を実行します。

  1. Button コンポーネントの内部handleClick という関数を宣言します。
  2. その関数内にロジックを実装します(ここでは alert を使ってメッセージを表示)。
  3. <button> の JSX に onClick={handleClick} を追加します。
export default function Button() {
  function handleClick() {
    alert('You clicked me!');
  }

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

handleClick 関数を定義し、それを <button>props の一部として渡しました。この handleClickイベントハンドラです。イベントハンドラ関数は:

  • 通常、コンポーネントの内部で定義されます。
  • イベント名の先頭に handle が付いた名前にします。

慣習的に、イベントハンドラは handle の後ろにイベントの名称をつなげた名前にすることが一般的です。onClick={handleClick}onMouseEnter={handleMouseEnter} などがよく見られます。

また、JSX の中でイベントハンドラをインラインで定義することもできます。

<button onClick={function handleClick() {
alert('You clicked me!');
}}>

または、より簡潔にアロー関数を使って記述することもできます。

<button onClick={() => {
alert('You clicked me!');
}}>

これらのスタイルはすべて同等です。インラインのイベントハンドラは、短い関数の場合に便利です。

落とし穴

イベントハンドラに渡す関数は、渡すべきなのであって、呼び出すべきではありません。例えば:

関数を渡す(正しい)関数を呼び出す(誤り)
<button onClick={handleClick}><button onClick={handleClick()}>

微妙に違いますね。最初の例では、handleClick 関数が onClick イベントハンドラとして渡されています。これは、React にこの関数を覚えておいて、ユーザがボタンをクリックしたときにのみコールするように指示します。

2 つ目の例では、handleClick() の末尾に () があるため、クリックを必要とせずレンダーの際にすぐに関数を実行します。これは、JSX の {}の中の JavaScript はすぐに実行されるためです。

インラインでコードを書くときにも、以下のように同様の落とし穴が別の形で現れます。

関数を渡す(正しい)関数を呼び出す(間違い)
<button onClick={() => alert('...')}><button onClick={alert('...')}>

このようなインラインコードを渡すと、クリックしたときではなく、コンポーネントがレンダーされるたびに実行されます。

// This alert fires when the component renders, not when clicked!
<button onClick={alert('You clicked me!')}>

イベントハンドラをインラインで定義したい場合は、以下のように無名関数でラップしてください。

<button onClick={() => alert('You clicked me!')}>

これで、レンダーごとに中のコードが実行されるのではなく、後で呼び出されるべき関数を作成したことになります。

どちらの場合であっても、渡したいのは関数です。

  • <button onClick={handleClick}>handleClick 関数を渡します。
  • <button onClick={() => alert('...')}> は、() => alert('...') という関数を渡します。

アロー関数についての詳細はこちら

イベントハンドラでの props の読み取り

イベントハンドラはコンポーネント内に宣言されているため、コンポーネントの props にアクセスできます。以下は、クリックされたときに message プロパティの内容をアラートで表示するボタンです。

function AlertButton({ message, children }) {
  return (
    <button onClick={() => alert(message)}>
      {children}
    </button>
  );
}

export default function Toolbar() {
  return (
    <div>
      <AlertButton message="Playing!">
        Play Movie
      </AlertButton>
      <AlertButton message="Uploading!">
        Upload Image
      </AlertButton>
    </div>
  );
}

これにより、これらの 2 つのボタンは異なるメッセージを表示できます。渡されるメッセージを変更してみてください。

イベントハンドラを props として渡す