私は通常のDOM CustomEvent
sを作成およびリッスンして、親ノードと通信します。
子供の場合:
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固有のより良い方法はありますか?
上記のように:
Reactの方法は、propsを介してコールバックを明示的に子に渡すことです。
リアクティブプログラミングの抽象化は直交しています:
オブザーバーパターンによるインタラクティブシステムのプログラミングは難しく、エラーが発生しやすく、それでも多くの実稼働環境での実装標準です。リアクティブプログラミングの抽象化を優先して、オブザーバーを徐々に非推奨にするアプローチを示します。いくつかのライブラリレイヤーは、プログラマがコールバックからより宣言的なプログラミングモデルに既存のコードをスムーズに移行するのに役立ちます。
React哲学は、代わりにコマンドパターンに基づいています。
参考文献
簡単なサービスを作成して使用できます
/** 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');
}
}
特に親から子、子へと穴を開けるのがすでに面倒になる場合、私が見つけた別のものも非常に合理的です。彼はそれをそれほど単純でないコミュニケーションと呼びました。リンクは次のとおりです。
https://github.com/ryanflorence/react-training/blob/gh-pages/lessons/04-less-simple-communication.md
コンテキストを介して渡されるコールバックを通じてイベントをバブルできます: [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;
考えられる解決策は、ReactJsアプリで絶対にmust Observerパターンに頼れば、通常のイベントをハイジャックできます。たとえば、削除キーを使用して、削除対象としてマークされた<div>
が必要な場合、<div>
に、customEventによって呼び出されるkeydownイベントをリッスンさせることができます。本文のキーダウンをトラップし、選択した<div>
でcustomEvent
keydownイベントを送出します。それが誰かを助ける場合に共有する。
状態をクライアントに配布し、状態をストアに戻す「ディスパッチ」中央ストア[Redux]は、オブザーバーパターンのようなものでもあります。パブリッシュ/サブスクライブを行う方法は、プロップ/イベントパスを接続する明示的な(脆弱な?)オーバーヘッドのために悪化するだけです。階層を切り抜けるReactは、悪臭を放つコンテキスト(プロバイダーパターン)または観察可能なライブラリを提供します。 @observableという新しいデコレータを導入するMobXや、新しいテンプレート構文「v-if」を導入するVueなど。とにかくイベントはDOMとjavascriptイベントループが動作する主要な方法です。悪魔主義者がやったと思う。笑
私はこの質問が今ではかなり古いことを知っていますが、この答えはまだ誰かを助けるかもしれません。 Reactの宣言的なカスタムイベントを追加するJSXプラグマを作成しました: jsx-native-events 。
基本的には、onEvent<EventName>
イベントを監視するパターン。
<some-custom-element onEventSomeEvent={ callback }></some-custom-element>