पेरेंट नोड्स के साथ संचार करने के लिए प्रतिक्रियाएँ


84

मैं सामान्य डोम के CustomEventलिए जनक नोड्स से संवाद करने के लिए बना रहा हूं और सुन रहा हूं :

बच्चे में:

  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);
},

यह काम करता है, लेकिन क्या कोई रिएक्ट-विशिष्ट तरीका है जो बेहतर होगा?


6
प्रतिक्रिया का तरीका स्पष्ट रूप से प्रॉम्प्स के माध्यम से बच्चों को कॉलबैक पास करना होगा - <Child onCustomEvent={this.handleCustomEvent} />। प्रतिक्रिया में w / bubbling कस्टम घटनाओं के लिए कोई समर्थन नहीं है।
andreypopp

14
तो, घटनाओं के बजाय कॉलबैक को बंद करें? उचित लगता है।
फॉरेस्टो

22
@forresto को व्यंग्य से प्यार है, +1
दिमितर क्रिस्टोफ़

12
मैं व्यंग्यात्मक नहीं था।
फॉरेस्टो

5
यह एक सबसे अच्छा व्यवहार स्थापित करने वाली एक बात है, एक व्यवहार्य पैटर्न को रोकने के लिए एक और पूरी तरह से। इस तरह के विपरीत कहने के लिए, twitter.github.io/flight - जो सिंथेटिक घटनाओं को बुलबुले और प्रचार करने के लिए डोन्वेंट का उपयोग करता है।
दिमित्र क्रिस्टोफ़

जवाबों:


47

जैसा कि ऊपर उल्लेखित है:

प्रतिक्रिया का तरीका स्पष्ट रूप से प्रॉम्प्स के माध्यम से बच्चों को कॉलबैक पास करना होगा -। प्रतिक्रिया में w / bubbling कस्टम घटनाओं के लिए कोई समर्थन नहीं है।

प्रतिक्रियाशील प्रोग्रामिंग मतिहीनता रूढ़िवादी है:

पर्यवेक्षक पैटर्न के माध्यम से इंटरैक्टिव सिस्टम प्रोग्रामिंग कठिन है और त्रुटि-प्रवण अभी भी कई उत्पादन वातावरण में कार्यान्वयन मानक है। हम प्रतिक्रियाशील प्रोग्रामिंग सार के पक्ष में धीरे-धीरे पर्यवेक्षकों को चित्रित करने के लिए एक दृष्टिकोण प्रस्तुत करते हैं। कई लाइब्रेरी लेयर्स प्रोग्रामर्स को कॉलबैक से मौजूदा कोड को अधिक डिक्लेक्टिव प्रोग्रामिंग मॉडल में आसानी से माइग्रेट करने में मदद करते हैं।

प्रतिक्रिया दर्शन इसके बजाय कमांड पैटर्न पर आधारित है:

यहां छवि विवरण दर्ज करें

संदर्भ


8
मुझे इस बात में दिलचस्पी है कि रीएक्ट में कस्टम सिंथेटिक इवेंट्स के लिए कोई सपोर्ट क्यों नहीं है। क्या यह केवल इतना है कि वे कभी लागू नहीं किए गए थे, या एक वैध डिजाइन निर्णय क्यों नहीं था? क्या घटनाओं को गोटो बयानों की तरह हानिकारक माना जाता है?
माइकल ब्यलस्ट्रा

4
@MichaelBylstra कस्टम घटनाओं की वजह से पर एक करने के लिए सिकोड़ी रहे हैं क्लासिक मुद्दा : a class of debugging problems where you don't know what triggers some code because of a long chain of events triggering other eventsआदेश पैटर्न के साथ एक तरह से डाटा प्रवाह दर्शन प्रतिक्रिया कर रहे हैं।
पॉल स्वेट्टे

2
इस तथ्य को ध्यान में रखते हुए कि घटक रिएक्ट संदर्भ के माध्यम से पूर्वज द्वारा इंजेक्ट किए गए घटक के साथ संवाद करते हैं, (Redux, रिएक्ट राउटर, आदि सभी संदर्भ का उपयोग करते हैं), यह कहने के लिए पूरी तरह से फर्जी है कि संदर्भ पर जो भी फ़ंक्शन है, उसके माध्यम से पूर्वजों को वापस बुला रहा है। मुहावरेदार प्रतिक्रिया। Redux "प्रेषण" को "एक्शन" ऑब्जेक्ट के साथ कॉल करने और "इवेंट हैंडलर" ऑब्जेक्ट के संदर्भ में "ईवेंट हैंडलर" कॉल करने के बीच कोई वास्तविक अंतर नहीं है।
एंडी

1
अन्य घटनाओं को ट्रिगर करने वाली घटनाओं की लंबी श्रृंखला काफी आम है जिस तरह से कुछ लोग Redux (जैसे redux-saga madness) का उपयोग करते हैं
एंडी

मुझे बात मिलती है, लेकिन मेरा एक सवाल है। चलो मान लेते हैं कि एक यूआई-किट लाइब्रेरी का निर्माण किया जाएगा, जिसका उद्देश्य कई आर्किटेक्चर में मूल रूप से काम करना है। कुछ घटकों को कस्टम घटनाओं को भेजने की आवश्यकता हो सकती है क्योंकि हम अज्ञात वास्तुकला के बारे में कुछ भी नहीं मान सकते हैं। रिएक्ट द्वारा की गई सख्त धारणा एक बड़े मुद्दे का परिणाम है। आप यहां समस्या की जांच कर सकते हैं ( custom-elements-everywhere.com ): रिएक्ट एकमात्र पुस्तकालय है जो ठीक से कस्टम ईवेंट को संभाल नहीं सकता है। हो सकता है, मुझे कुछ याद हो और किसी भी सुझाव की बहुत सराहना की जाएगी।
7uc4

7

आप एक साधारण सेवा लिख ​​सकते हैं और फिर उसका उपयोग कर सकते हैं

/** 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

आप कॉलबैक के माध्यम से घटनाओं को बुलबुला कर सकते हैं संदर्भों के माध्यम से पारित: [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;

3

एक और एक है जो मैंने पाया है जो काफी उचित है, खासकर अगर माता-पिता से बच्चे के लिए ड्रिलिंग छेद पहले से ही बोझिल हो जाते हैं। उन्होंने इसे कम सरल संचार कहा। यहाँ लिंक है:

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


यह मूल रूप से "ऑब्जर्वर पैटर्न को लागू करना" कह रहा है। मैं ओपी पर माइकल बाइलस्ट्रा की टिप्पणी से सहमत हूं, कम सरल संचार में "ड्रिलिंग छेद" के रूप में नोट की गई समस्या का वर्णन करते हुए ... बुदबुदाहट के बिना, कॉलबैक पास करना> 1 स्तर की गहरी संरचनाओं को संभालना नहीं है।
एरिकोस्को

3

सम्भावित समाधान, अगर आप पूरी तरह से होना चाहिए एक ReactJs में पर्यवेक्षक पैटर्न का सहारा आप एक सामान्य घटना का अपहरण कर सकते हैं एप्लिकेशन। उदाहरण के लिए, यदि आप चाहते हैं कि डिलीट कीज को डिलीट करने <div>के लिए चिह्नित किया जाए, तो आप <div>एक कीडाउन इवेंट के लिए सुन सकते हैं, जिसे एक कस्टमइनवेंट द्वारा लागू किया जाएगा। शरीर पर कीपैड को ट्रैप करें और customEventचयनित पर एक कीडाउन इवेंट को भेजें <div>। मामले में साझा करना किसी की मदद करता है।


3

एक केंद्रीय स्टोर [Redux] जो ग्राहकों को राज्य वितरित करता है, फिर स्टोर में वापस 'प्रेषण' राज्य एक पर्यवेक्षक पैटर्न की तरह है। केवल स्पष्ट (भंगुर?) ओवरहेड को जोड़ने के कारण प्रचार / घटनाओं के पथों को प्रकाशित / सदस्यता लेने का एक तरीका। पदानुक्रम के माध्यम से हैक करने के लिए रिएक्ट संदर्भ (प्रदाता पैटर्न) या बदबूदार पुस्तकालय प्रदान करता है जो बदबू करते हैं। MobX की तरह जो नए डेकोरेटर्स का परिचय करता है @observable, या Vue जो नए टेम्पलेट सिंटैक्स "v-if" का परिचय देता है। इवेंट का प्राथमिक तरीका है डोम और जावास्क्रिप्ट इवेंट लूप वैसे भी काम करते हैं, तो क्यों नहीं? मुझे लगता है कि शैतानी करने वालों ने ऐसा किया। जबरदस्त हंसी


1

मुझे पता है कि यह प्रश्न अब तक काफी पुराना है, लेकिन यह उत्तर अभी भी किसी की मदद कर सकता है। मैंने रिएक्ट के लिए एक JSX प्रैग्मेंट लिखा है जो घोषणात्मक कस्टम ईवेंट जोड़ता है: jsx-native- event ।

मूल रूप से आप सिर्फ onEvent<EventName>घटनाओं को देखने के लिए पैटर्न का उपयोग करते हैं।

<some-custom-element onEventSomeEvent={ callback }></some-custom-element>
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.