React イベント処理

React 要素のイベント処理は DOM 要素と似ています。ただし、構文上いくつか違いがあります:

  • React のイベントバインド属性の命名は小文字ではなくキャメルケース(camelCase)を使用します。
  • JSX 構文を使用する場合、イベントハンドラとして文字列(DOM 要素の書き方)ではなく関数を渡す必要があります。

HTML では通常次のように書きます:

<button onclick="activateLasers()">
  激活按钮
</button>

React では次のように書きます:

<button onClick={activateLasers}>
  激活按钮
</button>

React でのもう1つの違いは、return を使用してfalseデフォルトの動作を防ぐことはできません。明示的に使用する必要がありますpreventDefault。

例えば、通常 HTML でリンクがデフォルトで新しいページを開くのを防ぐには、次のように書きます:
<a href="../index.html" onclick="console.log('点击链接'); return false">
  点我
</a>

React での書き方は次のとおりです:

function ActionLink() { function handleClick(e) { e.preventDefault(); console.log('リンクがクリックされました'); } return ( <a href="#" onClick={handleClick}> クリック </a> ); }

この例では、e は合成イベント(SyntheticEvent)です。

React を使用するとき、通常は addEventListener を使用して作成済みの DOM 要素にリスナーを追加する必要はありません。要素の初期レンダリング時にリスナーを提供するだけで済みます。

ES6 の class 構文を使用してコンポーネントを定義する場合、イベントハンドラはクラスのメソッドになります。例えば、次の Toggle コンポーネントは、ユーザーがオン/オフ状態を切り替えられるボタンをレンダリングします:

例

class Toggle extends React.Component { constructor(props) { super(props); this.state = {isToggleOn: true}; //コールバック関数内で `this` を使用するには、ここでのバインドが必要です。 this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState(prevState => ({ isToggleOn: !prevState.isToggleOn })); } render() { return ( <button onClick={this.handleClick}> {this.state.isToggleOn ? 'ON' : 'OFF'} </button> ); } } const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <Toggle />, document.getElementById('example') );

試してみる »

JSX コールバック関数内の this には注意する必要があります。クラスのメソッドはデフォルトでは this にバインドされません。this.handleClick をバインドし忘れて onClick に渡した場合、その関数を呼び出したときの this の値は undefined になります。

これは React の特別な動作ではありません。JavaScript における関数の動作の一部です。通常、メソッドの後に () を付けない場合、例えばonClick={this.handleClick}このメソッドに this をバインドする必要があります。

bind の使用が面倒な場合、2つの解決方法があります。実験的なプロパティ初期化子(property initializer)構文を使用している場合は、プロパティ初期化子を使ってコールバック関数を正しくバインドできます:

class LoggingButton extends React.Component { //この構文により、`this` が handleClick にバインドされます。 //これはただのテストです。 handleClick = () => { console.log('this is:', this); } render() { return ( <button onClick={this.handleClick}> Click me </button> ); } }

プロパティ初期化子構文を使用していない場合は、コールバック関数内でアロー関数を使用できます:

class LoggingButton extends React.Component { handleClick() { console.log('this is:', this); } render() { //この構文により、`this` が handleClick にバインドされます。 return ( <button onClick={(e) => this.handleClick(e)}> Click me </button> ); } }

この構文には、LoggingButton がレンダリングされるたびに異なるコールバック関数が作成されるという問題があります。ほとんどの場合、これは問題ありません。しかし、このコールバック関数が props として下位コンポーネントに渡されると、それらのコンポーネントが余分に再レンダリングされる可能性があります。このようなパフォーマンスの問題を避けるために、通常はコンストラクタでバインドするか、プロパティ初期化子構文を使用することをお勧めします。


イベントハンドラにパラメータを渡す

通常、イベントハンドラには追加のパラメータを渡します。例えば、id が削除したい行の id である場合、次の2つの方法のいずれでもイベントハンドラにパラメータを渡せます:

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
上記の2つの方法は同等です。

上記の2つの例では、引数 e は React イベントオブジェクトとして2番目の引数として渡されます。アロー関数の場合は、イベントオブジェクトを明示的に渡す必要がありますが、bind の場合は、イベントオブジェクトやその他の引数が暗黙的に渡されます。

注意すべき点として、bind を使ってリスナー関数にパラメータを渡す場合、クラスコンポーネント内で定義されたリスナー関数では、イベントオブジェクト e は渡すパラメータの後ろに置く必要があります。例えば:

class Popper extends React.Component{ constructor(){ super(); this.state = {name:'Hello world!'}; } preventPop(name, e){ //イベントオブジェクト e は最後に置く必要があります。 e.preventDefault(); alert(name); } render(){ return ( <div> <p>hello</p> {/*bind() メソッドでパラメータを渡します。*/} <a href="https://reactjs.org" onClick={this.preventPop.bind(this,this.state.name)}>Click</a> </div> ); } }
その他の拡張