Skip to content

Latest commit

 

History

History

event-driven-app

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

This is a progressive tutorial to get familiar with some of the react-backbone event handling capabilities.

Running the examples

The source code can be found for each step in this tutorial in the current directory. To run each example, download the code and cd into an individual step and run

  npm install
  webpack-dev-server

then browse to http://localhost:8080

Step 1: baseline

As a baseline, we'll create a small app that has no react-backbone integration. This app renders 2 components that are decoupled but communicate by firing events on a global event bus. One of the components also listens for events on a child component that it renders out.

This is an alternate strategy to passing callback functions to child components as properties. Both work and it just depends on your individual development style and needs.

view source

Step 2: Use managed events for the child

view source

Component event handling is supported out of the box. You simply need to use the events mixin and add an events object to your component class. In this case, we are using the ref event handler so we need to make sure the child component has the ref property of child (if the event key was ref:foo:clicked, the child component would need a ref property of foo).

    var ComponentA = React.createClass({
      mixins: ['events'],

      events: {
        'ref:child:clicked': 'onChildClicked'
      },

And remove the current child component binding

    this.refs.child.on('clicked', this.onChildClicked);

The event will now be managed and, if the component with the child ref changes after a render, the events will be re-bound to the new component.

Step 3: Use triggerWith to apply scoped parameters

view source

The events mixin exposes a handy helper function called triggerWith. This provides a convenient way to apply scoped variables to a triggered event.

Include the events mixin for ComponentB

var ComponentB = React.createClass({
  mixins: ['events'],

Remove the scoped trigger function in ComponentB

    // remove this
    var eventParam = 'foo';
    var self = this;
    var triggerEvent = function() {
      self.triggerGlobalEvent(eventParam);
    };

We have no need for the triggerEvent method on ComponentB so remove that

    // remove this
    triggerEvent: function(eventParam) {
      this.trigger('clicked', eventParam);
    }

Use triggerWith to trigger the event and provide a scoped parameter in the render method of ComponentB

    <button type="button" onClick={this.triggerWith('clicked', 'foo')}>click me: Component1Child</button>

Use triggerWith to trigger the ComponentB global event (notice EventBus is the additional first parameter)

    <button type="button" onClick={this.triggerWith(EventBus, 'b:clicked')}>Click me: ComponentB</button>

And we have no need for the triggerGlobalEvent function in ComponentB so remove it

    // remove this
    triggerGlobalEvent: function() {
      // this will be triggered when this component's button is clicked
      EventBus.trigger('b:clicked');
    },

The events mixin will also provide implementations of on, once, off and trigger so remove the following code from Component1Child

    // remove this
    trigger: function() {
      return Backbone.Events.trigger.apply(this.state, arguments);
    },
    on: function() {
      return Backbone.Events.on.apply(this.state, arguments);
    },
    off: function() {
      return Backbone.Events.off.apply(this.state, arguments);
    },

Step 4: Create a custom event handler for the global event bus

view source

We can enhance what is available in the events object using React.events.handle. We will create a handler to trigger global event bus methods so we can use app:{event name} shorthand in our events object.

Define a variable for the react-events object

    var ReactEvents = require('react-events');

Register the custom event handler

    ReactEvents.handle('app', {
      target: EventBus
    });

Include the event bus reference in ComponentA

    events: {
      'ref:child:clicked': 'onChildClicked',
      'app:b:clicked': 'onComponentBClicked'
    },

We don't need our EventBus binding anymore in ComponentA so remove that

    // remove this
    componentDidMount: function() {
      // bind to the event bus to call our method onComponentBClicked when the global event "b:clicked" is triggered
      EventBus.on('b:clicked', this.onComponentBClicked);
    },
    componentWillUnmount: function() {
      EventBus.off('b:clicked', this.onComponentBClicked);
    },

Just to show what else we can do, you can also use functions as the events hash values. So, we'll change the events hash for ComponentA

    events: {
      'ref:child:clicked': function(eventParam) {
        alert('child was clicked; the event param is "' + eventParam + '"');
      },
      'app:b:clicked': 'onComponentBClicked'
    },

And remove the onChildClicked function in ComponentA

    // remove this
    onChildClicked: function(eventParam) {
      alert('child was clicked; the event param is "' + eventParam + '"');
    }

Now the code is clean and simple!

All done

All done but there is so much more you can do. Check out some of the other provided event handler types to see what else you can do.