1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【React】イベントハンドラー入門 - 通常のJavaScriptとの違いを理解しよう

Posted at

はじめに

Reactを学び始めた方が最初に戸惑うポイントの一つが、イベントハンドラーの書き方です。通常のJavaScriptでのDOM操作とは異なる記法や考え方が必要になります。

この記事では、Reactにおけるイベントハンドラーの基本から実践的な使い方まで、通常のJavaScriptとの違いを比較しながら解説していきます。

通常のJavaScriptとReactのイベントハンドラーの違い

まずは、通常のJavaScriptとReactでのイベントハンドラーの設定方法を比較してみましょう。

記法の違い

通常のJavaScript

// HTML
<button id="myButton">クリック</button>

// JavaScript
const button = document.getElementById('myButton');
button.addEventListener('click', function() {
  console.log('クリックされました');
});

// または
<button onclick="handleClick()">クリック</button>

React

function App() {
  const handleClick = () => {
    console.log('クリックされました');
  };

  return (
    <button onClick={handleClick}>クリック</button>
  );
}

Reactでは、JSX内に直接イベントハンドラーを記述するため、addEventListenerのようなメソッドは使いません。また、HTMLの属性として記述する場合と異なり、文字列ではなく関数を渡します。

イベント名の違い(キャメルケース)

通常のJavaScriptではイベント名が小文字ですが、Reactではキャメルケースで記述します。

通常のJavaScript React
onclick onClick
onchange onChange
onsubmit onSubmit
onmouseover onMouseOver
onkeydown onKeyDown
// 正しい書き方
<button onClick={handleClick}>クリック</button>

// 間違った書き方(動作しません)
<button onclick={handleClick}>クリック</button>

イベント伝播の扱い

デフォルト動作を防ぐ方法も異なりますね。

通常のJavaScript

element.addEventListener('click', function(e) {
  e.preventDefault();
  return false; // これも使える
});

React

const handleSubmit = (e) => {
  e.preventDefault(); // これが必要
};

<form onSubmit={handleSubmit}>
  {/* フォーム内容 */}
</form>

Reactではreturn falseによるデフォルト動作の防止は機能しないため、必ずe.preventDefault()を使用します。

thisの扱い方

クラスコンポーネントを使う場合、thisのバインディングに注意が必要です。ただし、関数コンポーネントとフックが主流の現在では、この問題はほとんど発生しません。

// クラスコンポーネントの例(参考)
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    // bindが必要
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    console.log(this); // bindしないとundefinedになる
  }

  render() {
    return <button onClick={this.handleClick}>クリック</button>;
  }
}

// 関数コンポーネントではthisの問題は発生しない
function MyComponent() {
  const handleClick = () => {
    console.log('クリックされました');
  };

  return <button onClick={handleClick}>クリック</button>;
}

Reactでのイベントハンドラーの基本的な書き方

関数コンポーネントでのイベントハンドラーの書き方を見ていきましょう。

関数コンポーネントでの実装

最も基本的な実装方法は、コンポーネント内で関数を定義し、それをJSX内で参照する形です。

function Counter() {
  const [count, setCount] = useState(0);

  const handleIncrement = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>カウント: {count}</p>
      <button onClick={handleIncrement}>増やす</button>
    </div>
  );
}

インラインでの記述

シンプルな処理であれば、インラインで記述することもできます。

function Greeting() {
  return (
    <button onClick={() => alert('こんにちは!')}>
      挨拶する
    </button>
  );
}

ただし、インラインで記述すると、レンダリングのたびに新しい関数が生成されるため、パフォーマンスが重要な場面では避けた方が良いでしょう。

関数を定義する方法

複数の書き方がありますが、アロー関数を使うのが一般的です。

function Example() {
  // アロー関数(推奨)
  const handleClick1 = () => {
    console.log('クリック1');
  };

  // 通常の関数
  function handleClick2() {
    console.log('クリック2');
  }

  return (
    <>
      <button onClick={handleClick1}>ボタン1</button>
      <button onClick={handleClick2}>ボタン2</button>
    </>
  );
}

よく使うイベントハンドラーの例

実際によく使用するイベントハンドラーを見ていきましょう。

onClick(クリックイベント)

ボタンのクリックや要素のクリックを検知します。

function ClickExample() {
  const [message, setMessage] = useState('');

  const handleClick = () => {
    setMessage('ボタンがクリックされました');
  };

  return (
    <div>
      <button onClick={handleClick}>クリック</button>
      <p>{message}</p>
    </div>
  );
}

onChange(入力イベント)

入力フィールドの値が変更されたときに発火します。フォームの制御でよく使いますね。

function InputExample() {
  const [text, setText] = useState('');

  const handleChange = (e) => {
    setText(e.target.value);
  };

  return (
    <div>
      <input 
        type="text" 
        value={text} 
        onChange={handleChange} 
      />
      <p>入力内容: {text}</p>
    </div>
  );
}

onSubmit(フォーム送信)

フォームの送信時に発火します。必ずpreventDefault()でデフォルトの送信動作を防ぎます。

function FormExample() {
  const [name, setName] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault(); // ページリロードを防ぐ
    console.log('送信された名前:', name);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input 
        type="text" 
        value={name} 
        onChange={(e) => setName(e.target.value)} 
      />
      <button type="submit">送信</button>
    </form>
  );
}

イベントオブジェクト(SyntheticEvent)の扱い方

Reactのイベントハンドラーに渡されるイベントオブジェクトは、ブラウザのネイティブイベントをラップしたSyntheticEvent(合成イベント)と呼ばれるものです。

イベントオブジェクトとは

SyntheticEventは、ブラウザ間の違いを吸収し、一貫したインターフェースを提供してくれます。

function EventExample() {
  const handleClick = (e) => {
    console.log(e); // SyntheticEventオブジェクト
    console.log(e.nativeEvent); // 元のブラウザイベント
  };

  return <button onClick={handleClick}>クリック</button>;
}

よく使うプロパティとメソッド

function DetailedEventExample() {
  const handleEvent = (e) => {
    // イベントの種類
    console.log(e.type); // 'click', 'change'など

    // イベントが発生した要素
    console.log(e.target); // イベントが発生したDOM要素
    console.log(e.currentTarget); // イベントハンドラーが設定された要素

    // 入力値の取得
    console.log(e.target.value); // input要素の値

    // デフォルト動作の防止
    e.preventDefault();

    // イベント伝播の停止
    e.stopPropagation();
  };

  return (
    <input 
      type="text" 
      onChange={handleEvent} 
    />
  );
}

主要なプロパティとメソッド

プロパティ/メソッド 説明
e.target イベントが発生した要素
e.currentTarget イベントハンドラーが設定された要素
e.target.value input要素などの値
e.preventDefault() デフォルト動作を防ぐ
e.stopPropagation() イベントの伝播を止める
e.type イベントの種類

イベントハンドラーに引数を渡す方法

イベントハンドラーに追加の引数を渡したい場合の方法を見ていきましょう。

アロー関数を使う方法

最も一般的で分かりやすい方法です。

function ListExample() {
  const items = ['りんご', 'バナナ', 'オレンジ'];

  const handleClick = (item) => {
    console.log(`${item}がクリックされました`);
  };

  return (
    <ul>
      {items.map((item, index) => (
        <li key={index}>
          <button onClick={() => handleClick(item)}>
            {item}
          </button>
        </li>
      ))}
    </ul>
  );
}

イベントオブジェクトも一緒に使いたい場合は、明示的に渡します。

function DetailedListExample() {
  const handleClick = (item, e) => {
    console.log('クリックされたアイテム:', item);
    console.log('イベントオブジェクト:', e);
  };

  return (
    <button onClick={(e) => handleClick('りんご', e)}>
      クリック
    </button>
  );
}

bind()を使う方法

bind()メソッドを使う方法もあります。ただし、現在ではあまり使われません。

function BindExample() {
  const handleClick = (item, e) => {
    console.log('アイテム:', item);
    console.log('イベント:', e);
  };

  return (
    <button onClick={handleClick.bind(null, 'りんご')}>
      クリック
    </button>
  );
}

アロー関数の方が読みやすいため、特別な理由がない限りアロー関数を使うことをおすすめします。

よくあるミスと注意点

初心者がよくやってしまうミスと、その対処法を見ていきましょう。

関数を実行してしまう間違い

イベントハンドラーには関数の参照を渡す必要がありますが、誤って関数を実行してしまうケースがあります。

function MistakeExample() {
  const handleClick = () => {
    console.log('クリックされました');
  };

  return (
    <div>
      {/* 正しい: 関数の参照を渡す */}
      <button onClick={handleClick}>正しい</button>

      {/* 間違い: 関数を実行している(レンダリング時に実行される) */}
      <button onClick={handleClick()}>間違い</button>

      {/* 引数を渡す場合はアロー関数で囲む */}
      <button onClick={() => handleClick()}>これは正しい</button>
    </div>
  );
}

onClick={handleClick()}と書くと、レンダリング時に関数が実行され、その返り値がイベントハンドラーとして設定されてしまいます。クリック時ではなく、画面表示時に実行されてしまうので注意が必要です。

無限ループに注意

状態更新とイベントハンドラーの組み合わせで、無限ループが発生することがあります。

function InfiniteLoopExample() {
  const [count, setCount] = useState(0);

  // 間違い: レンダリングのたびにsetCountが実行される
  return (
    <div>
      <p>{count}</p>
      <button onClick={setCount(count + 1)}>間違い</button>
    </div>
  );
}

function CorrectExample() {
  const [count, setCount] = useState(0);

  // 正しい: クリック時のみ実行される
  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>正しい</button>
      {/* または */}
      <button onClick={() => setCount(prev => prev + 1)}>これも正しい</button>
    </div>
  );
}

よくあるミスのまとめ

間違った書き方 正しい書き方 説明
onClick={handleClick()} onClick={handleClick} 関数の参照を渡す
onClick={setCount(count + 1)} onClick={() => setCount(count + 1)} アロー関数で囲む
onclick={handleClick} onClick={handleClick} キャメルケースで書く

まとめ

Reactのイベントハンドラーについて、以下のポイントを押さえておきましょう。

通常のJavaScriptとの主な違い

  • JSX内に直接記述する
  • イベント名はキャメルケースで書く
  • 関数の参照を渡す(文字列ではない)
  • return falseは機能しない

基本的な使い方

  • コンポーネント内で関数を定義してJSXで参照
  • インライン記述も可能だが、パフォーマンスに注意
  • イベントオブジェクトは自動的に渡される

注意すべき点

  • onClick={handleClick()}のように関数を実行しない
  • 引数を渡す場合はアロー関数で囲む
  • preventDefault()でデフォルト動作を防ぐ

これらの基本をマスターすれば、ReactでのインタラクティブなUIを作成できるようになります。最初は戸惑うかもしれませんが、慣れれば通常のJavaScriptよりも直感的に書けるようになりますよ。

1
2
0

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
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?