検索
ホームページウェブフロントエンドjsチュートリアルクリーンな React コンポーネント通信のためのイベント駆動型アーキテクチャ

React アプリケーションでのプロップのドリルリングとコールバック チェーンの終わりのないもつれにうんざりしていませんか?深くネストされたコンポーネント間の状態と通信の管理は、スパゲッティ コードと格闘するような感じですか?

イベント駆動型アーキテクチャは、コンポーネントの対話を簡素化し、複雑さを軽減し、アプリをより保守しやすくします。この記事では、カスタム useEvent フックを使用してコンポーネントを分離し、React アプリ全体の通信を改善する方法を説明します。

順を追って説明しましょう。まずは


問題: 小道具のドリルリングとコールバック チェーン

現代のアプリケーション開発では、コンポーネント間の状態と通信の管理がすぐに面倒になることがあります。これは、プロップ ドリル (複数レベルのネストされたコンポーネントを介してデータを渡す必要がある場合) や コールバック チェーン を含むシナリオに特に当てはまります。これにより、ロジックが複雑になり、コードの実行が困難になる可能性があります。メンテナンスまたはデバッグ。

これらの課題により、緊密に結合されたコンポーネントが作成されることが多く、柔軟性が低下し、アプリケーション内でデータがどのように流れるかを追跡しようとする開発者にとって認知的負荷が増大します。より良いアプローチがなければ、この複雑さによって開発が大幅に遅くなり、脆弱なコードベースにつながる可能性があります。

従来のフロー: プロップはダウン、コールバックはアップ

典型的な React アプリケーションでは、親コンポーネントが子に props を渡し、子はコールバックをトリガーすることで親に通信を返します。これは浅いコンポーネント ツリーではうまく機能しますが、階層が深くなると、状況が複雑になり始めます。

プロップドリル: データは、最も深いコンポーネントでのみ必要な場合でも、複数のレベルのコンポーネントを介して手動で受け渡す必要があります。

コールバック チェーン: 同様に、子コンポーネントはイベント ハンドラーをツリーの上に転送する必要があり、密結合で保守が難しい構造を作成します。

よくある問題: コールバックの複雑さ

次のシナリオを例に考えてみましょう:

  • 親は 子 A にプロップを渡します。
  • そこから、プロパティは GrandChildren A/B にドリルダウンされ、最終的には SubChildren N にドリルダウンされます。
  • SubChildren N が親にイベントを通知する必要がある場合、コールバック がトリガーされ、各中間コンポーネント を経由して戻ります。

アプリケーションが大きくなるにつれて、この設定の管理は難しくなります。中間コンポーネントは多くの場合、プロップとコールバックを転送する仲介者としてのみ機能するため、コードが肥大化して保守性が低下します。

Event-Driven Architecture for Clean React Component Communication

プロップドリルに対処するために、データ共有を合理化するために、グローバル状態管理ライブラリ (例: Zustand) などのソリューションに頼ることがよくあります。しかし、コールバックの管理についてはどうすればよいでしょうか?

ここで、イベント駆動型のアプローチが変革をもたらす可能性があります。コンポーネントを分離し、イベントに依存してインタラクションを処理することで、コールバック管理を大幅に簡素化できます。このアプローチがどのように機能するかを見てみましょう。


解決策: イベント駆動型アプローチを導入する

Event-Driven Architecture for Clean React Component Communication

ツリー上の通信に直接コールバックに依存するのではなく、イベント駆動型アーキテクチャによりコンポーネントが分離され、通信が集中化されます。仕組みは次のとおりです:

イベントのディスパッチ

SubChildren N がイベント (例: onMyEvent) をトリガーするとき、親のコールバックは直接呼び出されません。
代わりに、集中イベント ハンドラーによって処理されるイベントをディスパッチします

集中処理

イベント ハンドラーは、ディスパッチされたイベントをリッスンして処理します。
必要に応じて、親 (またはその他の関係するコンポーネント) に通知したり、追加のアクションをトリガーしたりできます。

プロップは下向きのまま

プロパティは引き続き階層の下に渡され、コンポーネントが機能するために必要なデータを確実に受け取ります。

これは、zustand、redux などの集中状態管理ツールで解決できますが、この記事では取り上げません。


実装

しかし、このアーキテクチャをどのように実装すればよいでしょうか?

useイベントフック

useEvent というカスタム フックを作成しましょう。このフックは、イベント サブスクリプションを処理し、ターゲット イベントをトリガーするディスパッチ関数を返す役割を果たします。

typescript を使用しているため、カスタム イベントを作成するにはウィンドウのイベント インターフェイスを拡張する必要があります。

interface AppEvent<payloadtype unknown> extends Event {
  detail: PayloadType;
}

export const useEvent = <payloadtype unknown>(
  eventName: keyof CustomWindowEventMap,
  callback?: Dispatch<payloadtype> | VoidFunction
) => {
  ...
};
</payloadtype></payloadtype></payloadtype>

そうすることで、カスタム イベント マップを定義し、カスタム パラメーターを渡すことができます。

interface AppEvent<payloadtype unknown> extends Event {
  detail: PayloadType;
}

export interface CustomWindowEventMap extends WindowEventMap {
  /* Custom Event */
  onMyEvent: AppEvent<string>; // an event with a string payload
}

export const useEvent = <payloadtype unknown>(
  eventName: keyof CustomWindowEventMap,
  callback?: Dispatch<payloadtype> | VoidFunction
) => {
  ...
};
</payloadtype></payloadtype></string></payloadtype>

必要なインターフェイスを定義したので、最終的なフック コードを見てみましょう

import { useCallback, useEffect, type Dispatch } from "react";

interface AppEvent<payloadtype unknown> extends Event {
  detail: PayloadType;
}

export interface CustomWindowEventMap extends WindowEventMap {
  /* Custom Event */
  onMyEvent: AppEvent<string>;
}

export const useEvent = <payloadtype unknown>(
  eventName: keyof CustomWindowEventMap,
  callback?: Dispatch<payloadtype> | VoidFunction
) => {
  useEffect(() => {
    if (!callback) {
      return;
    }

    const listener = ((event: AppEvent<payloadtype>) => {
      callback(event.detail); // Use `event.detail` for custom payloads
    }) as EventListener;

    window.addEventListener(eventName, listener);
    return () => {
      window.removeEventListener(eventName, listener);
    };
  }, [callback, eventName]);

  const dispatch = useCallback(
    (detail: PayloadType) => {
      const event = new CustomEvent(eventName, { detail });
      window.dispatchEvent(event);
    },
    [eventName]
  );

  // Return a function to dispatch the event
  return { dispatch };
};

</payloadtype></payloadtype></payloadtype></string></payloadtype>

useEvent フックは、カスタム ウィンドウ イベントをサブスクライブしてディスパッチするためのカスタム React フックです。これにより、カスタム イベントをリッスンし、特定のペイロードでそれらをトリガーすることができます。

ここで行っていることは非常に単純です。標準のイベント管理システムを使用し、カスタム イベントに対応するためにそれを拡張しています。

パラメータ:

  • eventName (文字列): リッスンするイベントの名前。
  • callback (オプション): イベントがトリガーされたときに呼び出す関数で、引数としてペイロードを受け取ります。

特徴:

  • イベント リスナー: 指定されたイベントをリッスンし、イベントの詳細 (カスタム ペイロード) を使用して提供されたコールバックを呼び出します。
  • イベントのディスパッチ: フックは、カスタム ペイロードでイベントをトリガーするディスパッチ関数を提供します。

例:

interface AppEvent<payloadtype unknown> extends Event {
  detail: PayloadType;
}

export const useEvent = <payloadtype unknown>(
  eventName: keyof CustomWindowEventMap,
  callback?: Dispatch<payloadtype> | VoidFunction
) => {
  ...
};
</payloadtype></payloadtype></payloadtype>

わかりました。でも、どうでしょうか?

現実世界の例?

この StackBlitz をチェックしてください (ロードされない場合は、ここで確認してください)

この簡単な例は useEvent フックの目的を示しています。基本的に本体のボタンは、サイドバー、ヘッダー、およびフッター コンポーネントからインターセプトされたイベントを送出し、それに応じて更新されます。

これにより、多くのコンポーネントにコールバックを伝播することなく、原因/結果反応を定義できるようになります。


useEvent の実世界の使用例

ここでは、useEvent フックが通信を簡素化し、React アプリケーション内のコンポーネントを分離できる、実際の使用例をいくつか示します。


1. 通知システム

通知システムでは、グローバルなコミュニケーションが必要になることがよくあります。

  • シナリオ:

    • API 呼び出しが成功すると、アプリ全体に「成功」​​通知が表示される必要があります。
    • ヘッダー内の「通知バッジ」などのコンポーネントも更新する必要があります。
  • 解決策: useEvent フックを使用して、通知の詳細を含む onNotification イベントを送出します。 NoticeBanner や Header などのコンポーネントは、このイベントをリッスンして個別に更新できます。

2. テーマの切り替え

ユーザーがテーマ (ライト/ダーク モードなど) を切り替えると、複数のコンポーネントが応答する必要がある場合があります。

  • シナリオ:

    • ThemeToggle コンポーネントはカスタムの onThemeChange イベントを送出します。
    • サイドバーやヘッダーなどのコンポーネントはこのイベントをリッスンし、それに応じてスタイルを更新します。
  • 利点: コンポーネント ツリー全体で props を介してテーマの状態やコールバック関数を渡す必要がありません。

3. グローバルキーバインド

「Ctrl S」を押して下書きを保存したり、「Escape」を押してモーダルを閉じるなどのグローバル ショートカットを実装します。

  • シナリオ:
    • グローバル キーダウン リスナーは、押されたキーの詳細を含む onShortcutPressed イベントを送出します。
    • モーダル コンポーネントまたはその他の UI 要素は、キー イベントの転送を親コンポーネントに依存せずに、特定のショートカットに応答します。

4. リアルタイム更新

チャット アプリやライブ ダッシュボードなどのアプリケーションでは、リアルタイムの更新に反応するために複数のコンポーネントが必要です。

  • シナリオ:
    • WebSocket 接続は、新しいデータが到着すると onNewMessage または onDataUpdate イベントを送出します。
    • チャット ウィンドウ、通知、未読メッセージ カウンターなどのコンポーネントは、独立して更新を処理できます。

5. コンポーネント間のフォーム検証

複数のセクションを持つ複雑なフォームの場合、検証イベントを一元化できます。

  • シナリオ:
    • ユーザーがフィールドに入力すると、フォーム コンポーネントは onFormValidate イベントを送出します。
    • 概要コンポーネントは、フォーム ロジックと密接に連携することなく、これらのイベントをリッスンして検証エラーを表示します。

6. 分析の追跡

ユーザーの操作 (ボタンのクリック、ナビゲーション イベントなど) を追跡し、分析サービスに送信します。

  • シナリオ:
    • 関連する詳細 (クリックされたボタンのラベルなど) を含む onUserInteraction イベントを送信します。
    • 中央分析ハンドラーはこれらのイベントをリッスンし、分析 API に送信します。

7. コラボレーションツール

共有ホワイトボードやドキュメントエディターなどの共同作業ツールの場合、イベントはマルチユーザーの対話を管理できます。

  • シナリオ:
    • ユーザーがオブジェクトを描画、入力、または移動するたびに onUserAction イベントを送出します。
    • 他のクライアントと UI コンポーネントはこれらのイベントをリッスンして、変更をリアルタイムで反映します。

これらのシナリオで useEvent フックを活用すると、深くネストされた props やコールバック チェーンに依存せずに、モジュール式で保守可能でスケーラブルなアプリケーションを作成できます。


結論

イベントは、複雑さを軽減し、モジュール性を向上させることで、React アプリケーションの構築方法を変革します。小規模から始めて、通信を分離することでメリットが得られるアプリ内のコンポーネントをいくつか特定し、useEvent フックを実装します。

このアプローチを使用すると、コードが簡素化されるだけでなく、将来の保守と拡張も容易になります。

イベントを使用する理由
イベントは、不要な依存関係や複雑なコールバック チェーンを導入することなく、アプリケーション内の他の場所で発生した何かにコンポーネントが反応する必要がある場合に威力を発揮します。このアプローチにより、認知負荷が軽減され、密結合コンポーネントの落とし穴が回避されます。

私のおすすめ
コンポーネント間の通信にはイベントを使用します。コンポーネント ツリー内の位置に関係なく、あるコンポーネントがアクションや状態の変化を他のコンポーネントに通知する必要がある場合に使用します。
コンポーネント内通信、特に密接に関連しているコンポーネントや直接接続されているコンポーネントの通信にイベントを使用することは避けてください。これらのシナリオでは、props、state、context などの React の組み込みメカニズムを利用します。

バランスの取れたアプローチ
イベントは強力ですが、使いすぎると混乱が生じる可能性があります。疎結合コンポーネント間の通信を簡素化するためにこれらを慎重に使用してください。ただし、ローカル インタラクションを管理するための React の標準ツールをそれらに置き換えさせないでください。

以上がクリーンな React コンポーネント通信のためのイベント駆動型アーキテクチャの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
Python vs. JavaScript:開発環境とツールPython vs. JavaScript:開発環境とツールApr 26, 2025 am 12:09 AM

開発環境におけるPythonとJavaScriptの両方の選択が重要です。 1)Pythonの開発環境には、Pycharm、Jupyternotebook、Anacondaが含まれます。これらは、データサイエンスと迅速なプロトタイピングに適しています。 2)JavaScriptの開発環境には、フロントエンドおよびバックエンド開発に適したnode.js、vscode、およびwebpackが含まれます。プロジェクトのニーズに応じて適切なツールを選択すると、開発効率とプロジェクトの成功率が向上する可能性があります。

JavaScriptはCで書かれていますか?証拠を調べるJavaScriptはCで書かれていますか?証拠を調べるApr 25, 2025 am 12:15 AM

はい、JavaScriptのエンジンコアはCで記述されています。1)C言語は、JavaScriptエンジンの開発に適した効率的なパフォーマンスと基礎となる制御を提供します。 2)V8エンジンを例にとると、そのコアはCで記述され、Cの効率とオブジェクト指向の特性を組み合わせて書かれています。3)JavaScriptエンジンの作業原理には、解析、コンパイル、実行が含まれ、C言語はこれらのプロセスで重要な役割を果たします。

JavaScriptの役割:WebをインタラクティブでダイナミックにするJavaScriptの役割:WebをインタラクティブでダイナミックにするApr 24, 2025 am 12:12 AM

JavaScriptは、Webページのインタラクティブ性とダイナミズムを向上させるため、現代のWebサイトの中心にあります。 1)ページを更新せずにコンテンツを変更できます。2)Domapiを介してWebページを操作する、3)アニメーションやドラッグアンドドロップなどの複雑なインタラクティブ効果、4)ユーザーエクスペリエンスを改善するためのパフォーマンスとベストプラクティスを最適化します。

CおよびJavaScript:接続が説明しましたCおよびJavaScript:接続が説明しましたApr 23, 2025 am 12:07 AM

CおよびJavaScriptは、WebAssemblyを介して相互運用性を実現します。 1)CコードはWebAssemblyモジュールにコンパイルされ、JavaScript環境に導入され、コンピューティングパワーが強化されます。 2)ゲーム開発では、Cは物理エンジンとグラフィックスレンダリングを処理し、JavaScriptはゲームロジックとユーザーインターフェイスを担当します。

Webサイトからアプリまで:JavaScriptの多様なアプリケーションWebサイトからアプリまで:JavaScriptの多様なアプリケーションApr 22, 2025 am 12:02 AM

JavaScriptは、Webサイト、モバイルアプリケーション、デスクトップアプリケーション、サーバー側のプログラミングで広く使用されています。 1)Webサイト開発では、JavaScriptはHTMLおよびCSSと一緒にDOMを運用して、JQueryやReactなどのフレームワークをサポートします。 2)ReactNativeおよびIonicを通じて、JavaScriptはクロスプラットフォームモバイルアプリケーションを開発するために使用されます。 3)電子フレームワークにより、JavaScriptはデスクトップアプリケーションを構築できます。 4)node.jsを使用すると、JavaScriptがサーバー側で実行され、高い並行リクエストをサポートします。

Python vs. JavaScript:ユースケースとアプリケーションと比較されますPython vs. JavaScript:ユースケースとアプリケーションと比較されますApr 21, 2025 am 12:01 AM

Pythonはデータサイエンスと自動化により適していますが、JavaScriptはフロントエンドとフルスタックの開発により適しています。 1. Pythonは、データ処理とモデリングのためにNumpyやPandasなどのライブラリを使用して、データサイエンスと機械学習でうまく機能します。 2。Pythonは、自動化とスクリプトにおいて簡潔で効率的です。 3. JavaScriptはフロントエンド開発に不可欠であり、動的なWebページと単一ページアプリケーションの構築に使用されます。 4. JavaScriptは、node.jsを通じてバックエンド開発において役割を果たし、フルスタック開発をサポートします。

JavaScript通訳者とコンパイラにおけるC/Cの役割JavaScript通訳者とコンパイラにおけるC/Cの役割Apr 20, 2025 am 12:01 AM

CとCは、主に通訳者とJITコンパイラを実装するために使用されるJavaScriptエンジンで重要な役割を果たします。 1)cは、JavaScriptソースコードを解析し、抽象的な構文ツリーを生成するために使用されます。 2)Cは、Bytecodeの生成と実行を担当します。 3)Cは、JITコンパイラを実装し、実行時にホットスポットコードを最適化およびコンパイルし、JavaScriptの実行効率を大幅に改善します。

JavaScript in Action:実際の例とプロジェクトJavaScript in Action:実際の例とプロジェクトApr 19, 2025 am 12:13 AM

現実世界でのJavaScriptのアプリケーションには、フロントエンドとバックエンドの開発が含まれます。 1)DOM操作とイベント処理を含むTODOリストアプリケーションを構築して、フロントエンドアプリケーションを表示します。 2)node.jsを介してRestfulapiを構築し、バックエンドアプリケーションをデモンストレーションします。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

mPDF

mPDF

mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

SecLists

SecLists

SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

VSCode Windows 64 ビットのダウンロード

VSCode Windows 64 ビットのダウンロード

Microsoft によって発売された無料で強力な IDE エディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

WebStorm Mac版

WebStorm Mac版

便利なJavaScript開発ツール