ReactでDOMとウィンドウイベントを処理する方法
著者は、 Creative Commons を選択して、 Write forDOnationsプログラムの一環として寄付を受け取りました。
序章
Web開発では、eventsはWebブラウザーで発生するアクションを表します。 イベントハンドラーを使用してイベントに応答することにより、マウスでのクリック、Webページのスクロール、タッチスクリーンのタッチなど、あらゆるユーザーアクションに応答する動的なJavaScriptアプリケーションを作成できます。もっと。
React アプリでは、イベントハンドラーを使用して、状態データを更新したり、 prop の変更をトリガーしたり、デフォルトのブラウザーアクションを防止したりできます。 これを行うために、Reactは SyntheticEvent
ネイティブイベントインターフェイスの代わりにラッパー。 SyntheticEvent
標準のブラウザイベントを厳密にエミュレートしますが、さまざまなWebブラウザに対してより一貫した動作を提供します。 Reactは、コンポーネントが Document Object Model(DOM)にマウントおよびアンマウントするときに、 Window イベントリスナーを安全に追加および削除するためのツールも提供し、制御を可能にします。 Window
メモリリークが不適切に削除されたリスナーからのイベントを防止します。
このチュートリアルでは、Reactでイベントを処理する方法を学びます。 自己検証型の入力コンポーネントや入力フォームの有益なツールチップなど、ユーザーイベントを処理するいくつかのサンプルコンポーネントを作成します。 チュートリアル全体を通して、コンポーネントにイベントハンドラーを追加し、から情報を取得する方法を学習します。 SyntheticEvent
、および追加と削除 Window
イベントリスナー。 このチュートリアルを終えると、さまざまなイベントハンドラーを操作して、Reactでサポートされているイベントのカタログを適用できるようになります。
前提条件
-
Node.jsを実行する開発環境が必要になります。 このチュートリアルは、Node.jsバージョン10.22.0およびnpmバージョン6.14.6でテストされました。 これをmacOSまたはUbuntu18.04にインストールするには、Node.jsをインストールしてmacOSにローカル開発環境を作成する方法またはの
PPAを使用したインストール ]セクションの手順に従います。 Ubuntu18.04にNode.jsをインストールする方法。 -
Create React App でセットアップされたReact開発環境で、不要なボイラープレートが削除されています。 これを設定するには、ステップ1 —Reactクラスコンポーネントの状態を管理する方法のチュートリアルの空のプロジェクトを作成します。 このチュートリアルでは、
events-tutorial
プロジェクト名として。 -
また、JavaScriptとHTMLの基本的な知識も必要です。これは、HTMLシリーズでWebサイトを構築する方法およびJavaScriptでコーディングする方法にあります。 CSSの基本的な知識も役立ちます。これは、 Mozilla DeveloperNetworkで見つけることができます。
-
Reactコンポーネントを使用します。
useState
フック、そしてuseReducer
チュートリアルReactでカスタムコンポーネントを作成する方法およびReactコンポーネントのフックで状態を管理する方法で学ぶことができるフック。
ステップ1—でイベントデータを抽出する SyntheticEvent
このステップでは、を使用して検証コンポーネントを作成します <input>
HTML要素と onChange
イベントハンドラ。 このコンポーネントは、入力を受け入れて検証するか、コンテンツが特定のテキストパターンに準拠していることを確認します。 を使用します SyntheticEvent
イベントデータをコールバック関数に渡し、からのデータを使用してコンポーネントを更新するラッパー <input>
. また、から関数を呼び出します SyntheticEvent
、 そのような preventDefault
標準のブラウザアクションを防ぐため。
Reactでは、イベントリスナーを追加する前に要素を選択する必要はありません。 代わりに、小道具を使用してJSXにイベントハンドラーを直接追加します。 React には、でサポートされているイベントが多数あります。これには、次のような一般的なイベントが含まれます。 onClick
また onChange
となどのあまり一般的ではないイベント onWheel
.
ネイティブDOMoneventハンドラーとは異なり、Reactはと呼ばれる特別なラッパーを渡します SyntheticEvent
ネイティブブラウザではなくイベントハンドラに Event
. 抽象化は、ブラウザー間の不整合を減らすのに役立ち、コンポーネントにイベントを操作するための標準インターフェースを提供します。 のAPI SyntheticEvent
ネイティブに似ています Event
、したがって、ほとんどのタスクは同じ方法で実行されます。
これを実証するために、検証入力を行うことから始めます。 まず、というコンポーネントを作成します FileNamer
. これは <form>
ファイルに名前を付けるための入力を持つ要素。 入力を入力すると、コンポーネントの上にあるプレビューボックスが更新される情報が表示されます。 コンポーネントには、検証を実行するための送信ボタンも含まれますが、この例では、フォームは実際には何も送信しません。
まず、ディレクトリを作成します。
- mkdir src/components/FileNamer
次に開きます FileNamer.js
テキストエディタで:
- nano src/components/FileNamer/FileNamer.js
中身 FileNamer.js
、ラッパーを作成します <div>
、次に別の <div>
クラス名は preview
と <form>
次のコード行を記述して、ラッパー内の要素を作成します。
import React from 'react';
export default function FileNamer() {
return(
<div className="wrapper">
<div className="preview">
</div>
<form>
</form>
</div>
)
}
次に、プレビューボックスに表示する名前の入力要素と保存ボタンを追加します。 次の強調表示された行を追加します。
import React from 'react';
export default function FileNamer() {
return(
<div className="wrapper">
<div className="preview">
<h2>Preview:</h2>
</div>
<form>
<label>
<p>Name:</p>
<input name="name" />
</label>
<div>
<button>Save</button>
</div>
</form>
</div>
)
}
の中に preview
<div>
、追加しました <h2>
テキスト付きの要素 Preview
. これがプレビューボックスになります。 フォーム内に、 <input>
に囲まれています <label>
要素と Name:
そのテキストとして。 次に、を追加しました button
クロージングの直前にSaveと呼ばれます <form>
鬼ごっこ。
ファイルを保存して閉じます。
次に、開く App.js
:
- nano src/components/App/App.js
輸入 FileNamer
、次に内部でレンダリングします App
次の強調表示された行を追加して機能します。
import React from 'react';
import FileNamer from '../FileNamer/FileNamer';
function App() {
return <FileNamer />
}
export default App;
ファイルを保存して閉じます。 これを行うと、ブラウザが更新され、コンポーネントが表示されます。
次に、セクションを定義し、要素にパディングとマージンを追加するために、いくつかの軽いスタイルを追加します。
開ける FileNamer.css
テキストエディタで:
- nano src/components/FileNamer/FileNamer.css
与える .preview
灰色の境界線とパディングを分類してから、 .wrapper
少量のパディングを分類します。 flexとを使用して列に項目を表示します flex-direction
、すべてのテキストを左揃えにします。 最後に、境界線を削除して黒い境界線を追加することにより、デフォルトのボタンスタイルを削除します。
.preview {
border: 1px darkgray solid;
padding: 10px;
}
.wrapper {
display: flex;
flex-direction: column;
padding: 20px;
text-align: left;
}
.wrapper button {
background: none;
border: 1px black solid;
margin-top: 10px;
}
ファイルを保存して閉じます。 次に開きます FileNamer.js
:
- nano src/components/FileNamer/FileNamer.js
スタイルをインポートして、コンポーネントに適用します。
import React from 'react';
import './FileNamer.css';
export default function FileNamer() {
return(
<div className="wrapper">
<div className="preview">
<h2>Preview:</h2>
</div>
<form>
<label>
<p>Name:</p>
<input name="name" />
</label>
<div>
<button>Save</button>
</div>
</form>
</div>
)
}
ファイルを保存します。 これを行うと、ブラウザが更新され、コンポーネントに新しいスタイルが追加されていることがわかります。
基本的なコンポーネントができたので、イベントハンドラーをに追加できます。 <input>
エレメント。 ただし、最初に、入力フィールドにデータを保存する場所が必要になります。 useState Hook を追加して、入力を保持します。
import React, { useState } from 'react';
import './FileNamer.css';
export default function FileNamer() {
const [name, setName] = useState('');
return(
<div className="wrapper">
<div className="preview">
<h2>Preview: {name}.js</h2>
</div>
<form>
<label>
<p>Name:</p>
<input name="name" />
</label>
<div>
<button>Save</button>
</div>
</form>
</div>
)
}
このコードでは、構造を解除しました useState
変数に name
入力と呼び出される関数を保持します setName
データを更新します。 次に、 name
プレビューセクションに続いて .js
ユーザーがファイルに名前を付けているかのように、拡張子。
入力データを保存できるようになったので、イベントハンドラーをに追加できます。 <input>
成分。 多くの場合、特定のタスクに使用できるいくつかの異なるイベントハンドラーがあります。 この場合、アプリはユーザーが要素に入力したデータをキャプチャする必要があります。 この状況で最も一般的なハンドラーは onChange
、コンポーネントが変更されるたびに起動します。 ただし、キーボードイベントなどを使用することもできます。 onKeyDown
, onKeyPress
、 と onKeyUp
. 違いは主に、イベントが発生したときと情報が SyntheticEvent
物体。 例えば、 onBlur
、要素の焦点が合わなくなったときのイベントが前に発生します onClick
. 別のイベントが発生する前にユーザー情報を処理する場合は、以前のイベントを選択できます。
イベントの選択は、渡すデータのタイプによっても決まります。 SyntheticEvent
. The onKeyPress
たとえば、イベントには charCode
ユーザーが押したキーの onChange
特定の文字コードは含まれませんが、完全な入力が含まれます。 これは、ユーザーが押したキーに応じて異なるアクションを実行する場合に重要です。
このチュートリアルでは、 onChange
最新のキーだけでなく、入力値全体をキャプチャします。 これにより、変更のたびに値を格納して連結する手間が省けます。
を取る関数を作成します event
引数として、それをに渡します <input>
を使用する要素 onChange
小道具:
import React, { useState } from 'react';
import './FileNamer.css';
export default function FileNamer() {
const [name, setName] = useState('');
return(
<div className="wrapper">
<div className="preview">
<h2>Preview: {name}.js</h2>
</div>
<form>
<label>
<p>Name:</p>
<input name="name" onChange={event => {}}/>
</label>
<div>
<button>Save</button>
</div>
</form>
</div>
)
}
前述のように、 event
これはネイティブブラウザイベントではありません。 それは SyntheticEvent
多くの場合同じように扱われるReactによって提供されます。 まれに、ネイティブイベントが必要な場合は、 nativeEvent
の属性 SyntheticEvent
.
イベントができたので、現在の値を target.value
イベントのプロパティ。 値をに渡す setName
プレビューを更新するには:
import React, { useState } from 'react';
import './FileNamer.css';
export default function FileNamer() {
const [name, setName] = useState('');
return(
<div className="wrapper">
<div className="preview">
<h2>Preview: {name}.js</h2>
</div>
<form>
<label>
<p>Name:</p>
<input
autoComplete="off"
name="name"
onChange={event => setName(event.target.value) }
/>
</label>
<div>
<button>Save</button>
</div>
</form>
</div>
)
}
さらに、属性autoCompleteをに設定します "off"
ブラウザの提案をオフにします。
ファイルを保存します。 これを行うと、ページがリロードされ、入力すると <input>
プレビューに更新が表示されます。
注:を使用して入力の名前にアクセスすることもできます event.target.name
. これは、複数の入力で同じイベントハンドラーを使用している場合に役立ちます。これは、 name
自動的に一致します name
コンポーネントの属性。
この時点で、作業中のイベントハンドラーがあります。 ユーザー情報を取得して状態に保存し、データで別のコンポーネントを更新しています。 ただし、イベントから情報を取得するだけでなく、フォームの送信を防止したり、キー押下アクションを防止したりする場合など、イベントを停止する必要がある場合があります。
イベントを停止するには、 preventDefault
イベントのアクション。 これにより、ブラウザはデフォルトの動作を実行できなくなります。
の場合 FileNamer
コンポーネントには、アプリが禁止するファイルを選択するプロセスを中断する可能性のある特定の文字があります。 たとえば、ユーザーに追加してほしくない場合 *
ワイルドカード文字と競合するため、ファイル名に変更します。ワイルドカード文字は、別のファイルセットを参照していると解釈される可能性があります。 ユーザーがフォームを送信する前に、無効な文字がないことを確認する必要があります。 無効な文字がある場合は、ブラウザによるフォームの送信を停止し、ユーザーへのメッセージを表示します。
まず、生成するフックを作成します alert
booleanおよび setAlert
関数。 次に、 <div>
メッセージを表示するには alert
本当です:
import React, { useState } from 'react';
import './FileNamer.css';
export default function FileNamer() {
const [name, setName] = useState('');
const [alert, setAlert] = useState(false);
return(
<div className="wrapper">
<div className="preview">
<h2>Preview: {name}.js</h2>
</div>
<form>
<label>
<p>Name:</p>
<input
autoComplete="off"
name="name"
onChange={event => setName(event.target.value) }
/>
</label>
{alert && <div> Forbidden Character: *</div>}
<div>
<button>Save</button>
</div>
</form>
</div>
)
}
このコードでは、 &&
新しいものだけを表示する演算子 <div>
もしも alert
に等しく設定されます true
最初。 のメッセージ <div>
ユーザーに次のように伝えます *
入力に文字を使用することはできません。
次に、という関数を作成します validate
. 正規表現.testメソッドを使用して、文字列に *
. その場合、フォームの送信を防ぐことができます。
import React, { useState } from 'react';
import './FileNamer.css';
export default function FileNamer() {
const [name, setName] = useState('');
const [alert, setAlert] = useState(false);
const validate = event => {
if(/\*/.test(name)) {
event.preventDefault();
setAlert(true);
return;
}
setAlert(false);
};
return(
<div className="wrapper">
<div className="preview">
<h2>Preview: {name}.js</h2>
</div>
<form>
<label>
<p>Name:</p>
<input
autoComplete="off"
name="name"
onChange={event => setName(event.target.value) }
/>
</label>
{alert && <div> Forbidden Character: *</div>}
<div>
<button onClick={validate}>Save</button>
</div>
</form>
</div>
)
}
いつ validate
関数が呼び出され、テストが返されます true
、使用します event.preventDefault
その後、電話 setAlert(true)
. それ以外の場合は、 setAlert(false)
. コードの最後の部分で、イベントハンドラーをに追加しました <button>
要素と onClick
.
ファイルを保存します。 以前のように、あなたも使用することができます onMouseDown
、 しかし onClick
より一般的であるため、予期しない副作用を回避できます。 このフォームには送信アクションはありませんが、デフォルトのアクションを禁止することで、ページが再読み込みされないようにします。
これで、2つのイベントハンドラーを使用するフォームができました。 onChange
と onClick
. イベントハンドラーを使用して、ユーザーアクションをコンポーネントとアプリケーションに接続し、インタラクティブにします。 そうすることで、DOM要素にイベントを追加する方法と、同じアクションで発生するが、 SyntheticEvent
. また、から情報を抽出する方法も学びました SyntheticEvent
、そのデータを状態に保存して他のコンポーネントを更新し、を使用してイベントを停止します preventDefault
.
次のステップでは、さまざまなユーザーアクションを処理するために、単一のDOM要素に複数のイベントを追加します。
ステップ2—同じ要素に複数のイベントハンドラーを追加する
1つのコンポーネントで複数のイベントが発生する場合があり、1つのコンポーネントでさまざまなイベントに接続できる必要があります。 たとえば、このステップでは、 onFocus
と onBlur
コンポーネントに関するジャストインタイム情報をユーザーに提供するイベントハンドラー。 このステップを終えると、Reactでサポートされているさまざまなイベントと、それらをコンポーネントに追加する方法について詳しく知ることができます。
The validate
関数は、フォームが不正なデータを送信するのを防ぐのに役立ちますが、ユーザーエクスペリエンスにはあまり役立ちません。ユーザーは、フォーム全体に入力した後にのみ、有効な文字に関する情報を受け取ります。 複数のフィールドがある場合、最後のステップまでユーザーにフィードバックは提供されません。 このコンポーネントをよりユーザーフレンドリーにするために、ユーザーがフィールドに入力するときに許可されている文字と許可されていない文字を表示して、 onFocus
イベントハンドラ。
まず、更新します alert
<div>
許可される文字に関する情報を含めるため。 ユーザーに英数字が許可されていることと、 *
許可されていません:
import React, { useState } from 'react';
import './FileNamer.css';
export default function FileNamer() {
...
return(
<div className="wrapper">
<div className="preview">
<h2>Preview: {name}.js</h2>
</div>
<form>
<label>
<p>Name:</p>
<input
autocomplete="off"
name="name"
onChange={event => setName(event.target.value) }
/>
</label>
{alert &&
<div>
<span role="img" aria-label="allowed">✅</span> Alphanumeric Characters
<br />
<span role="img" aria-label="not allowed">⛔️</span> *
</div>
}
<div>
<button onClick={validate}>Save</button>
</div>
</form>
</div>
)
}
このコードでは、 Accessible Rich Internet Applications(ARIA)標準を使用して、コンポーネントをスクリーンリーダーでよりアクセスしやすくしました。
次に、別のイベントハンドラーをに追加します <input>
エレメント。 入力をクリックまたはタブで入力してコンポーネントをアクティブ化すると、許可されている文字と許可されていない文字についてユーザーに警告します。 次の強調表示された行を追加します。
import React, { useState } from 'react';
import './FileNamer.css';
export default function FileNamer() {
...
return(
<div className="wrapper">
<div className="preview">
<h2>Preview: {name}.js</h2>
</div>
<form>
<label>
<p>Name:</p>
<input
autocomplete="off"
name="name"
onChange={event => setName(event.target.value) }
onFocus={() => setAlert(true)}
/>
</label>
{alert &&
<div>
<span role="img" aria-label="allowed">✅</span> Alphanumeric Characters
<br />
<span role="img" aria-label="not allowed">⛔️</span> *
</div>
}
<div>
<button onClick={validate}>Save</button>
</div>
</form>
</div>
)
}
追加しました onFocus
イベントハンドラー <input>
エレメント。 このイベントは、ユーザーがフィールドを選択したときにトリガーされます。 イベントハンドラーを追加した後、匿名関数をに渡しました onFocus
それは setAlert(true)
データを表示します。 この場合、からの情報は必要ありません。 SyntheticEvent
; ユーザーが行動したときにのみイベントをトリガーする必要があります。 Reactはまだ送信しています SyntheticEvent
関数に追加しますが、現在の状況では、関数内の情報を使用する必要はありません。
注:でデータ表示をトリガーできます onClick
あるいは onMouseDown
、ただし、キーボードを使用してフォームフィールドにタブで移動するユーザーはアクセスできません。 この場合、 onFocus
イベントは両方のケースを処理します。
ファイルを保存します。 これを行うと、ブラウザが更新され、ユーザーが入力をクリックするまで情報が非表示のままになります。
フィールドにフォーカスがあるときにユーザー情報が表示されるようになりましたが、データはコンポーネントの期間中存在します。 それをなくす方法はありません。 幸いなことに、という別のイベントがあります onBlur
これは、ユーザーが入力を離れたときに発生します。 追加します onBlur
を設定する匿名関数を持つイベントハンドラー alert
に false
. お気に入り onFocus
、これは、ユーザーがクリックしたとき、またはユーザーがタブで移動したときの両方で機能します。
import React, { useState } from 'react';
import './FileNamer.css';
export default function FileNamer() {
...
return(
<div className="wrapper">
<div className="preview">
<h2>Preview: {name}.js</h2>
</div>
<form>
<label>
<p>Name:</p>
<input
autocomplete="off"
name="name"
onBlur={() => setAlert(false)}
onChange={event => setName(event.target.value) }
onFocus={() => setAlert(true)}
/>
</label>
{alert &&
<div>
<span role="img" aria-label="allowed">✅</span> Alphanumeric Characters
<br />
<span role="img" aria-label="not allowed">⛔️</span> *
</div>
}
<div>
<button onClick={validate}>Save</button>
</div>
</form>
</div>
)
}
ファイルを保存します。 これを行うと、ブラウザが更新され、ユーザーが要素をクリックすると情報が表示され、ユーザーがクリックすると情報が消えます。
要素に必要な数のイベントハンドラーを追加できます。 必要なイベントのアイデアはあるが名前がわからない場合は、サポートされているイベントをスクロールすると、必要なものが見つかる可能性があります。
このステップでは、単一のDOM要素に複数のイベントハンドラーを追加しました。 さまざまなイベントハンドラーが、クリックとタブの両方などの幅広いイベント、または狭い範囲のイベントをどのように処理できるかを学びました。
次のステップでは、グローバルイベントリスナーをに追加します Window
直接のコンポーネントの外部で発生するイベントをキャプチャするオブジェクト。
ステップ3—ウィンドウイベントの追加
このステップでは、ユーザー情報をポップアップコンポーネントに配置します。このポップアップコンポーネントは、ユーザーが入力にフォーカスするとアクティブになり、ユーザーがページ上の他の場所をクリックすると閉じます。 この効果を実現するには、 useEffect Hook を使用して、グローバルイベントリスナーをWindowオブジェクトに追加します。 また、コンポーネントがアンマウントされたとき、メモリリークを防ぐため、アプリが必要以上のメモリを消費したときに、イベントリスナーを削除します。
この手順を完了すると、個々のコンポーネントでイベントリスナーを安全に追加および削除できるようになります。 また、使用方法も学びます useEffect
コンポーネントがマウントおよびアンマウントされるときにアクションを実行するためのフック。
ほとんどの場合、JSXのDOM要素にイベントハンドラーを直接追加します。 これにより、コードに焦点が当てられ、コンポーネントが別のコンポーネントの動作を制御しているという混乱した状況を防ぐことができます。 Window
物体。 ただし、グローバルイベントリスナーを追加する必要がある場合があります。 たとえば、スクロールリスナーで新しいコンテンツをロードしたり、コンポーネントの外部でクリックイベントをキャプチャしたりできます。
このチュートリアルでは、ユーザーが特に要求した場合にのみ、入力に関する情報をユーザーに表示します。 情報を表示した後、ユーザーがコンポーネントの外部のページをクリックするたびに情報を非表示にする必要があります。
開始するには、 alert
新しいに表示 <div>
とともに className
の information-wrapper
. 次に、新しいボタンを追加します className
の information
と onClick
呼び出すイベント setAlert(true)
:
import React, { useState } from 'react';
import './FileNamer.css';
export default function FileNamer() {
...
return(
<div className="wrapper">
<div className="preview">
<h2>Preview: {name}.js</h2>
</div>
<form>
<label>
<p>Name:</p>
<input
autocomplete="off"
name="name"
onChange={event => setName(event.target.value) }
/>
</label>
<div className="information-wrapper">
<button
className="information"
onClick={() => setAlert(true)}
type="button"
>
more information
</button>
{alert &&
<div className="popup">
<span role="img" aria-label="allowed">✅</span> Alphanumeric Characters
<br />
<span role="img" aria-label="not allowed">⛔️</span> *
</div>
}
</div>
<div>
<button onClick={validate}>Save</button>
</div>
</form>
</div>
)
}
また、 onFocus
と onBlur
からのハンドラー <input>
最後のステップから動作を削除する要素。
ファイルを保存して閉じます。 次に開きます FileNamer.css
:
- nano src/components/FileNamer/FileNamer.css
絶対に配置するためにいくつかのスタイリングを追加します popup
ボタンの上の情報。 次に、 <button>
のクラスで information
境界線のない青になります。
.information {
font-size: .75em;
color: blue;
cursor: pointer;
}
.wrapper button.information {
border: none;
}
.information-wrapper {
position: relative;
}
.popup {
position: absolute;
background: white;
border: 1px darkgray solid;
padding: 10px;
top: -70px;
left: 0;
}
.preview {
border: 1px darkgray solid;
padding: 10px;
}
.wrapper {
display: flex;
flex-direction: column;
padding: 20px;
text-align: left;
}
.wrapper button {
background: none;
border: 1px black solid;
margin-top: 10px;
}
ファイルを保存して閉じます。 これを行うと、ブラウザがリロードされ、クリックすると more information
、コンポーネントに関する情報が表示されます。
これでポップアップをトリガーできますが、それをクリアする方法はありません。 この問題を修正するには、を呼び出すグローバルイベントリスナーを追加します setAlert(false)
ポップアップの外側をクリックすると。
イベントリスナーは次のようになります。
window.addEventListener('click', () => setAlert(false))
ただし、コードでイベントリスナーを設定するときは注意が必要です。 たとえば、コンポーネントコードの先頭にイベントリスナーを追加することはできません。これは、何かが変更されるたびに、コンポーネントが再レンダリングされて新しいイベントリスナーが追加されるためです。 コンポーネントは何度も再レンダリングされる可能性が高いため、メモリを消費する未使用のイベントリスナーが多数作成されます。
これを解決するために、Reactには特別なフックがあります useEffect
これは、特定のプロパティが変更された場合にのみ実行されます。 基本的な構造は次のとおりです。
useEffect(() => {
// run code when anything in the array changes
}, [someProp, someOtherProp])
簡略化された例では、Reactは匿名関数でコードを実行します someProp
また someOtherProp
変更します。 配列内の項目は依存関係と呼ばれます。 このフックは、依存関係の変更をリッスンし、変更後に関数を実行します。
これで、を使用してグローバルイベントリスナーを安全に追加および削除するためのツールができました。 useEffect
いつでもイベントリスナーを追加する alert
は true
いつでもそれを削除します alert
は false
.
もう1つのステップがあります。 コンポーネントがアンマウントされると、内部から戻ってきた関数が実行されます useEffect
針。 このため、コンポーネントがアンマウントされたときにイベントリスナーを削除する関数も返す必要があります。
基本的な構造は次のようになります。
useEffect(() => {
// run code when anything in the array changes
return () => {} // run code when the component unmounts
}, [someProp, someOtherProp])
今、あなたはあなたの形を知っています useEffect
フック、アプリケーションで使用します。 開く FileNamer.js
:
- nano src/components/FileNamer/FileNamer.js
内部、インポート useEffect
、次に依存関係のある空の無名関数を追加します alert
と setAlert
関数の後の配列内:
import React, { useEffect, useState } from 'react';
import './FileNamer.css';
export default function FileNamer() {
const [name, setName] = useState('');
const [alert, setAlert] = useState(false);
useEffect(() => {
}, [alert, setAlert]);
...
このコードでは、両方を追加しました alert
と setAlert
. 完了するために、Reactはすべての外部依存関係をに追加することをお勧めします useEffect
関数。 あなたが呼び出すので setAlert
関数、それは依存関係と見なすことができます。 setAlert
最初のレンダリング後は変更されませんが、依存関係と見なされる可能性のあるものをすべて含めることをお勧めします。
次に、無名関数内に、という新しい関数を作成します handleWindowClick
それは setAlert(false)
:
import React, { useEffect, useState } from 'react';
import './FileNamer.css';
export default function FileNamer() {
const [name, setName] = useState('');
const [alert, setAlert] = useState(false);
useEffect(() => {
const handleWindowClick = () => setAlert(false)
}, [alert, setAlert]);
...
}
次に、条件付きを追加します。 window.addEventListener('click', handleWindowClick)
いつ alert
は true
と電話します window.removeEventListener('click', handleWindowClick)
いつ alert
は false
. これにより、ポップアップをトリガーするたびにイベントリスナーが追加され、ポップアップが閉じられるたびにイベントリスナーが削除されます。
import React, { useEffect, useState } from 'react';
import './FileNamer.css';
export default function FileNamer() {
const [name, setName] = useState('');
const [alert, setAlert] = useState(false);
useEffect(() => {
const handleWindowClick = () => setAlert(false)
if(alert) {
window.addEventListener('click', handleWindowClick);
} else {
window.removeEventListener('click', handleWindowClick);
}
}, [alert, setAlert]);
...
}
最後に、イベントリスナーを削除する関数を返します。 繰り返しますが、これはコンポーネントがアンマウントされたときに実行されます。 ライブイベントリスナーがない場合もありますが、リスナーがまだ存在する状況では、クリーンアップする価値があります。
import React, { useEffect, useState } from 'react';
import './FileNamer.css';
export default function FileNamer() {
const [name, setName] = useState('');
const [alert, setAlert] = useState(false);
useEffect(() => {
const handleWindowClick = () => setAlert(false)
if(alert) {
window.addEventListener('click', handleWindowClick);
} else {
window.removeEventListener('click', handleWindowClick)
}
return () => window.removeEventListener('click', handleWindowClick);
}, [alert, setAlert]);
...
}
ファイルを保存します。 これを行うと、ブラウザが更新されます。 詳細情報ボタンをクリックすると、メッセージが表示されます。 開発ツールでグローバルイベントリスナーを見ると、 click
リスナー:
コンポーネントの外側をクリックします。 メッセージが消え、グローバルクリックイベントリスナーが表示されなくなります。
君の useEffect
フックは、ユーザーの操作に基づいてグローバルイベントリスナーを正常に追加および削除しました。 特定のDOM要素に関連付けられていませんでしたが、代わりにコンポーネントの状態の変更によってトリガーされました。
注:アクセシビリティの観点から、このコンポーネントは完全ではありません。 ユーザーがマウスを使用できない場合、コンポーネントの外側をクリックすることはできないため、ポップアップが開いたままになります。 解決策は、次のイベントリスナーを追加することです。 keydown
メッセージも削除されます。 メソッドが次のようになることを除いて、コードはほぼ同じになります keydown
それ以外の click
.
このステップでは、コンポーネント内にグローバルイベントリスナーを追加しました。 また、使用方法も学びました useEffect
状態の変化に応じてイベントリスナーを適切に追加および削除し、コンポーネントがアンマウントされたときにイベントリスナーをクリーンアップする方法をフックします。
結論
イベントハンドラーを使用すると、コンポーネントをユーザーアクションに合わせることができます。 これらは、アプリケーションに豊かなエクスペリエンスを提供し、アプリのインタラクティブな可能性を高めます。 また、ユーザーのアクションをキャプチャして応答する機能も提供します。
Reactのイベントハンドラーを使用すると、イベントコールバックをHTMLと統合しておくことができるため、アプリケーション全体で機能とデザインを共有できます。 ほとんどの場合、イベントハンドラをDOM要素に直接追加することに重点を置く必要がありますが、コンポーネントの外部でイベントをキャプチャする必要がある状況では、イベントリスナーを追加し、使用されなくなったときにクリーンアップして、メモリリークを防ぐことができます。パフォーマンスの高いアプリケーションを作成します。
Reactのチュートリアルをもっと見たい場合は、 Reactトピックページを確認するか、React.jsシリーズのコーディング方法ページに戻ってください。 JavaScriptでのイベントの詳細については、JavaScriptでのイベントの理解およびNode.jsでのイベントエミッターの使用のチュートリアルをご覧ください。