Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react.js custom events for communicating with parent nodes

Tags:

reactjs

I'm making and listening for normal DOM CustomEvents to communicate to parent nodes:

In child:

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

In parent:

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

This works, but is there a React-specific way that would be better?

like image 308
forresto Avatar asked Feb 22 '14 08:02

forresto


2 Answers

As noted above:

The React way would be to pass callbacks down to children explicitly via props — . There's no support for custom events w/ bubbling in React.

The reactive programming abstraction is orthogonal:

Programming interactive systems by means of the observer pattern is hard and error-prone yet is still the implementation standard in many production environments. We present an approach to gradually deprecate observers in favor of reactive programming abstractions. Several library layers help programmers to smoothly migrate existing code from callbacks to a more declarative programming model.

The React philosophy is based on the Command pattern instead:

enter image description here

References

  • Deprecating the Observer Pattern
  • Command Pattern: Command History
  • Component Interop with React and Custom Elements
  • Building Redux in TypeScript
  • How is Mithril Different from Other Frameworks - Mithril
like image 69
8 revs Avatar answered Oct 12 '22 11:10

8 revs


you can write a simple service and then use it

/** 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];   }, }; 

example (same for triggering)

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');   } } 
like image 31
Ivan Maslov Avatar answered Oct 12 '22 12:10

Ivan Maslov