React is great in terms of its virtual DOM, and JSX makes the code so much more readable.
When leveraging React in terms of Rails, I highly recommend the reactjs/react-rails gem as this integrates it with the help of the asset pipeline, allowing one to setup components in app/assets/javascripts/components
thanks to a components.js
manifest file.
However, I wanted to be able to trigger components to re-render using an event system such as Backbone.Events
, although for this quick example, I will be using EventEmitter.
$(function () {
var globalEmitter = new EventEmitter();
var triggerEmitter = function (payload) {
console.log("Event payload %O", payload);
globalEmitter.emit('change', payload);
};
var makeChangeEventMixin = function (emitter) {
return {
componentDidMount: function () {
emitter.addListener('change', this.__makeChangeEventMixin_handler_);
},
componentWillUnmount: function () {
emitter.removeListener('change', this.__makeChangeEventMixin_handler_);
},
__makeChangeEventMixin_handler_: function (payload) {
console.log('__makeChangeEventMixin_handler_ fired with payload=%O', payload);
this.replaceState(payload);
}
};
};
var UIComponent = React.createClass({
mixins: [makeChangeEventMixin(globalEmitter)],
getInitialState: function () {
return {
data: {
name: ''
}
};
},
render: function () {
var data = this.state.data;
console.log('Data: %O', data);
return React.DOM.div(null,
React.DOM.span(null, "Hi there '" + data.name + "'"))
}
});
React.render(
React.createElement(UIComponent),
document.getElementById('example'));
$('#trigger--button').on('click', function (e) {
e.preventDefault();
triggerEmitter({
data: {
name: "Mike"
}
})
});
});
The above contrived example (Fiddle) renders a component on screen and the button's click event triggers a re-render of the component, passing along the payload data.
Typically, React goes hand-in-hand with Flux, which aids in establishing a predictable data layer. I hope to get into Flux at some point, but for this rather simplistic use-case, I'm rather happy with this event-driven approach.