1

I am using ReactJS and i have connected socket as in the different file as global function. There is a message event listener of socket and fires when any new message comes from backend.

Now what i want is that, i want to fire an event into component when my message event listener fires as it is defined as a global function.

Can anyone have an idea, how we do ?

Thanks in advance

4

1 に答える 1

0

https://codesandbox.io/s/13287npq03で、いくつかの (カスタム) イベント ディスパッチの例を作成しました。(イベントはコンソールに記録されます - コンソールをクリックして展開しますここに画像の説明を入力)

基本:

  1. React コンポーネント内で発生したイベントを取得する場合は、イベント リスナーを追加する必要があります。ベスト プラクティスは、componentDidMount 内に追加することです。

    componentDidMount = () => { let element = document.getElementById("idOfEventListener"); element.addEventListener("eventname", this.eventListener); };

Component render メソッドのいずれかの内部にその要素が必要であることに注意してください。例えばrender() { return <div id="idOfEventListener" /> }

  1. イベントが発生したときにトリガーされるメソッドが必要です。element.addEventListener("イベント名", this.eventListener); の代わりに インライン関数を作成することもできますelement.addEventListener("eventname", e => console.log('event occured', e));。それ以外の場合は、コンポーネント内にイベント リスナー メソッドを作成する必要があります。

    eventListener = e => { console.log("event occured in component", e, e.target); };

  2. ベスト プラクティスは、コンポーネントのアンマウント時にクリーンアップ (イベント リスナーを削除) することです。

    componentWillUnmount = () => { let element = document.getElementById("idOfEventListener"); element.removeEventListener( "eventname", EventHelper.dispatchCustomEvent, false ); };

https://codesandbox.io/s/13287npq03の説明:

EventHelper.js

汎用の dispatchCustomEvent メソッドを別のファイル内に作成したので、任意のコンポーネントからそれを使用 (およびイベントをディスパッチ) できます。ターゲット (DOM 要素、例: document.getElementById('idOfEventListener'))、イベント名 (リッスンしている名前と同じである必要があります。上記の addEventListener では、「イベント名」のみをリッスンしていると指定しました) および詳細を受け入れます ->提供したいカスタムデータ、オブジェクト/文字列/数値など、必要なものは何でも。

export default {
  dispatchCustomEvent: (target, name, details) => {
    if (target) {
      let event = new Event(name, {
        details: details,
        bubbles: true,
        cancelable: true
      });

      target.dispatchEvent(event);
    }
  }
};

上記のイベントリスナーの場合、 を呼び出す必要がEventHelper.dispatchCustomEvent(document.getElementById("idOfEventListener"), "eventname", {test: "whatever data you need"})あり、リスナーは this.eventListener メソッドとコンソールログ event & event.target (DOM element になります) をトリガーします。

メッセージイベントリスナーが起動したときに EventHelper.dispatchCustomEvent を呼び出すことができます。または、メッセージイベントがどのように見えるかを知っている場合は、必要なコンポーネント内でそのメッセージイベントをリッスンできます。メッセージイベントがグローバルである場合、ウィンドウまたはドキュメントでイベントを作成していると思います-次のようにコンポーネントでイベントリスナーを作成する必要があります:

  componentDidMount = () => {
    let element = window || document;

    element.addEventListener("messageEventName", this.eventListener);
  };

  eventListener = e => {
    console.log("event inside second child component:", e, e.target);
  };

  componentWillUnMount = () => {
    let element = window || document;
    element.removeEventListener(
      "messageEventName",
      EventHelper.dispatchCustomEvent,
      false
    );
  };

その他のコンポーネント:

index.js

2 つの子コンポーネント FirstChildComponent と SecondChildComponent を持つメイン/親コンポーネント。レンダリング内に 2 つのボタンを作成しました。最初のボタンは、FirstChildComponent がリッスンしているイベントを発生させ、2 番目のボタンは、親 (index.js) と SecondChildComponent によってリッスンされているイベント「eventname」を発生させ、両方をトリガーします。親と 2 番目の子のイベント リスナー。そのイベントをウィンドウまたはドキュメントにバインドする代わりに、<div id="idOfEventListener">アプリケーション全体のラッパーである作成したことに注意してください。SecondChildComponent と親の両方がそれをイベント リスナー ターゲットとして使用し、それをターゲットとするイベントを取得できます。

import React, { Component } from "react";
import FirstChildComponent from "./FirstChildComponent";
import SecondChildComponent from "./SecondChildComponent";
import ReactDOM from "react-dom";
import EventHelper from "./EventHelper";

class App extends Component {
  componentDidMount = () => {
    let element = document.getElementById("idOfEventListener");

    element.addEventListener("eventname", this.eventListener);
  };

  eventListener = e => {
    console.log("event in parent component", e, e.target);
  };

  componentWillUnMount = () => {
    let element = document.getElementById("idOfEventListener");
    element.removeEventListener(
      "eventname",
      EventHelper.dispatchCustomEvent,
      false
    );
  };

  fireEvent = () => {
    let additionalData = { loremIpsum: "dolor sit amet" };
    let target = document.getElementById("FirstChildEventListener");
    EventHelper.dispatchCustomEvent(
      target,
      "firstChildEventName",
      additionalData
    );
  };

  fireMultipleListenedEvent = () => {
    console.log("fire multiple");
    let additionalData = { test: "blabla" };
    let target = document.getElementById("idOfEventListener");
    EventHelper.dispatchCustomEvent(target, "eventname", additionalData);
  };

  render() {
    return (
      <div id="idOfEventListener" className="App">
        <h1>Parent Component</h1>
        <div id="GettingEventInParentComponent">
          Box in parent component listening for event
        </div>
        <button onClick={this.fireEvent}>
          Test Button that will fire event which FirstComponent will receive
        </button>

        <FirstChildComponent />
        <SecondChildComponent />

        <hr />

        <button onClick={this.fireMultipleListenedEvent}>
          Test Button that will fire event which is listened inside of Second
          Child Component and parent component both
        </button>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

FirstChildComponent

FirstChildComponent render ( <p id="FirstChildEventListener">) 内のターゲットでイベントをリッスンし、そのイベントは別のコンポーネント内でトリガーされます (親ですが、SecondChildComponent から簡単にトリガーでき、リスナーは引き続きそれを取得します)。

import React, { Component } from "react";
import EventHelper from "./EventHelper";

export default class FirstChildComponent extends Component {
  componentDidMount = () => {
    var element = document.getElementById("FirstChildEventListener");

    element.addEventListener("firstChildEventName", this.eventListener);
  };

  eventListener = e => {
    console.log("event inside first child component:", e, e.target);
  };

  componentWillUnMount = () => {
    var element = document.getElementById("FirstChildEventListener");
    element.removeEventListener(
      "firstChildEventName",
      EventHelper.dispatchCustomEvent,
      false
    );
  };

  render() {
    return (
      <div className="App">
        <h1>First Child Component</h1>
        <p id="FirstChildEventListener">
          This element is inside of FirstChildComponent, and it only listens
          when event will be dispatched
        </p>
      </div>
    );
  }
}

SecondChildComponent.js

render の外側にある (親) DOM 要素のイベントをリッスンします。

import React, { Component } from "react";
import EventHelper from "./EventHelper";

export default class FirstChildComponent extends Component {
  componentDidMount = () => {
    let element = document.getElementById("idOfEventListener");

    element.addEventListener("eventname", this.eventListener);
  };

  eventListener = e => {
    console.log("event inside second child component:", e, e.target);
  };

  componentWillUnMount = () => {
    let element = document.getElementById("idOfEventListener");
    element.removeEventListener(
      "eventname",
      EventHelper.dispatchCustomEvent,
      false
    );
  };

  render() {
    return (
      <div className="App">
        <h1>Second Child Component</h1>
        <span>Listening event on upper level</span>
      </div>
    );
  }
}

親コンポーネントからイベントを発生させていますが(ボタンのクリック時)、メッセージイベントリスナー内でイベントを発生させてから、必要なコンポーネント内でその正確なイベントのイベントリスナーを作成できます。


編集


websocket の例で GlobalFile.js を codesandbox に追加しました。

import EventHelper from "./EventHelper";

// or just copy dispatchCustomEvent function
/*function dispatchCustomEvent (target, name, details) {
  if (target) {
    let event = new Event(name, {
      details: details,
      bubbles: true,
      cancelable: true
    });

    target.dispatchEvent(event);
  }
}*/

let jsWebSocket = null;

function initSocket(user_id) {
  jsWebSocket = new WebSocket("wss://demos.kaazing.com/echo");
  jsWebSocket.addEventListener("open", function(event) {
    jsWebSocket.addEventListener("message", function(event) {
      console.log("message listener fired");
      let elementInsideOfComponent = document.getElementById(
        "elementInsideOfComponnet"
      );
      let someData = { id: "message1" };
      // if element target exists dispatch event to component
      console.log(elementInsideOfComponent);
      if (elementInsideOfComponent)
        EventHelper.dispatchCustomEvent(
          elementInsideOfComponent,
          "websocketmessage",
          someData
        );
    });
  });
}

function sendMessage() {
  jsWebSocket.send("Here's some text that the server is urgently awaiting!");
}

export default { initSocket, sendMessage, jsWebSocket };

<div id="elementInsideOfComponnet">Listening for global message</div>websocket メッセージ イベントからディスパッチされるイベントのターゲットとなるDOM 要素を含む ComponentListeningForGlobalEvent.js を追加しました。

import React, { Component } from "react";
import EventHelper from "./EventHelper";

export default class ComponentListeningForGlobalEvent extends Component {
  componentDidMount = () => {
    let element = document.getElementById("elementInsideOfComponnet");

    element.addEventListener("websocketmessage", this.eventListener);
  };

  eventListener = e => {
    console.log("websocketmessage event inside component:", e, e.target);
  };

  componentWillUnMount = () => {
    let element = document.getElementById("elementInsideOfComponnet");
    element.removeEventListener(
      "websocketmessage",
      EventHelper.dispatchCustomEvent,
      false
    );
  };

  render() {
    return (
      <div className="App">
        <h1>Component that will receive event from websocket</h1>

        <div id="elementInsideOfComponnet">Listening for global message</div>
      </div>
    );
  }
}

また追加:

  constructor(props) {
    super(props);

    GlobalFile.initSocket("id");
  }

index.js (親コンポーネント) に、websocket 接続を初期化します。そして、index.js のレンダリングに:

<ComponentListeningForGlobalEvent />
<button onClick={GlobalFile.sendMessage}>Send websocket message</button>

Websocket メッセージからイベントを受信するコンポーネントを挿入し、websocket 送信メッセージをトリガーするボタンを挿入して、Websocket メッセージ イベントが ComponentListeningForGlobalEvent まで伝搬されることをテスト (および確認) できます。

これが役立つことを本当に願っています!:)

于 2018-06-15T09:33:05.080 に答える