web-dev-qa-db-ja.com

親ノードと通信するためのreact.jsカスタムイベント

私は通常のDOM CustomEventsを作成およびリッスンして、親ノードと通信します。

子供の場合:

  var moveEvent = new CustomEvent('the-graph-group-move', { 
    detail: {
      nodes: this.props.nodes,
      x: deltaX,
      y: deltaY
    },
    bubbles: true
  });
  this.getDOMNode().dispatchEvent(moveEvent);

親で:

componentDidMount: function () {
  this.getDOMNode().addEventListener("the-graph-group-move", this.moveGroup);
},

これは機能しますが、React固有のより良い方法はありますか?

65
forresto

上記のように:

Reactの方法は、propsを介してコールバックを明示的に子に渡すことです。

リアクティブプログラミングの抽象化は直交しています:

オブザーバーパターンによるインタラクティブシステムのプログラミングは難しく、エラーが発生しやすく、それでも多くの実稼働環境での実装標準です。リアクティブプログラミングの抽象化を優先して、オブザーバーを徐々に非推奨にするアプローチを示します。いくつかのライブラリレイヤーは、プログラマがコールバックからより宣言的なプログラミングモデルに既存のコードをスムーズに移行するのに役立ちます。

React哲学は、代わりにコマンドパターンに基づいています。

enter image description here

参考文献

37
Paul Sweatte

簡単なサービスを作成して使用できます

/** eventsService */
module.exports = {
  callbacks: {},

  /**
   * @param {string} eventName
   * @param {*} data
   */
  triggerEvent(eventName, data = null) {
    if (this.callbacks[eventName]) {
      Object.keys(this.callbacks[eventName]).forEach((id) => {
        this.callbacks[eventName][id](data);
      });
    }
  },

  /**
   * @param {string} eventName name of event
   * @param {string} id callback identifier
   * @param {Function} callback
   */
  listenEvent(eventName, id, callback) {
    this.callbacks[eventName][id] = callback;
  },

  /**
   * @param {string} eventName name of event
   * @param {string} id callback identifier
   */
  unlistenEvent(eventName, id) {
    delete this.callbacks[eventName][id];
  },
};

例(トリガーと同じ)

import eventsService from '../../../../services/events';
export default class FooterMenu extends Component {
  componentWillMount() {
    eventsService
      .listenEvent('cart', 'footer', this.cartUpdatedListener.bind(this));
  }

  componentWillUnmount() {
    eventsService
      .unlistenEvent('cart', 'footer');
  }

  cartUpdatedListener() {
    console.log('cart updated');
  }
}
4
Dr.Tranquility

特に親から子、子へと穴を開けるのがすでに面倒になる場合、私が見つけた別のものも非常に合理的です。彼はそれをそれほど単純でないコミュニケーションと呼びました。リンクは次のとおりです。

https://github.com/ryanflorence/react-training/blob/gh-pages/lessons/04-less-simple-communication.md

3
index

コンテキストを介して渡されるコールバックを通じてイベントをバブルできます: [CodePen]

import * as React from 'react';

const MyEventContext = React.createContext(() => {});

const MyEventBubbleContext = ({children, onMyEvent}) => {
  const bubbleEvent = React.useContext(MyEventContext);
  const handleMyEvent = React.useCallback((...args) => {
    // stop propagation if handler returns false
    if (onMyEvent(...args) !== false) {
      // bubble the event
      bubbleEvent(...args);
    }
  }, [onMyEvent]);
  return (
    <MyEventContext.Provider value={handleMyEvent}>
      {children}
    </MyEventContext.Provider>
  );
};

const MyComponent = () => (
  <MyEventBubbleContext onMyEvent={e => console.log('grandparent got event: ', e)}>
    <MyEventBubbleContext onMyEvent={e => console.log('parent got event: ', e)}>
      <MyEventContext.Consumer>
        {onMyEvent => <button onClick={onMyEvent}>Click me</button>}
      </MyEventContext.Consumer>
    </MyEventBubbleContext>
  </MyEventBubbleContext>
);

export default MyComponent;
2
Andy

考えられる解決策は、ReactJsアプリで絶対にmust Observerパターンに頼れば、通常のイベントをハイジャックできます。たとえば、削除キーを使用して、削除対象としてマークされた<div>が必要な場合、<div>に、customEventによって呼び出されるkeydownイベントをリッスンさせることができます。本文のキーダウンをトラップし、選択した<div>customEvent keydownイベントを送出します。それが誰かを助ける場合に共有する。

2
Doug

状態をクライアントに配布し、状態をストアに戻す「ディスパッチ」中央ストア[Redux]は、オブザーバーパターンのようなものでもあります。パブリッシュ/サブスクライブを行う方法は、プロップ/イベントパスを接続する明示的な(脆弱な?)オーバーヘッドのために悪化するだけです。階層を切り抜けるReactは、悪臭を放つコンテキスト(プロバイダーパターン)または観察可能なライブラリを提供します。 @observableという新しいデコレータを導入するMobXや、新しいテンプレート構文「v-if」を導入するVueなど。とにかくイベントはDOMとjavascriptイベントループが動作する主要な方法です。悪魔主義者がやったと思う。笑

1
user982671

私はこの質問が今ではかなり古いことを知っていますが、この答えはまだ誰かを助けるかもしれません。 Reactの宣言的なカスタムイベントを追加するJSXプラグマを作成しました: jsx-native-events

基本的には、onEvent<EventName>イベントを監視するパターン。

<some-custom-element onEventSomeEvent={ callback }></some-custom-element>
0
Caleb Williams