This is a progressive tutorial to get familiar with some of the react-backbone
event handling capabilities.
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
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.
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.
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);
},
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 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.