Skip to content

Instantly share code, notes, and snippets.

@Alex-Shilman
Forked from BinaryMuse/README.md
Created September 28, 2015 12:08
Show Gist options
  • Select an option

  • Save Alex-Shilman/46dc48741ab405d0f8cb to your computer and use it in GitHub Desktop.

Select an option

Save Alex-Shilman/46dc48741ab405d0f8cb to your computer and use it in GitHub Desktop.
Integrating React with Marionette

Integrating React with Marionette

See ReactComponentView and BackboneModelWatchMixin, below.

Notes

The BackboneModelWatchView could use some additional methods to allow adding/removing watched models after the component is created.

Example

// marionette_ticket_view.js

var Marionette = require("marionette"),
    ReactComponentView = require("./mixins/react_component_view"),
    TicketViewComponent = require("./ticket_view_component");

module.exports = Marionette.View.extend(ReactComponentView).extend({
  initialize: function(options) {
    this.ticket = options.model;
  },

  getReactComponent: function() {
    return TicketViewComponent({ticket: this.ticket});
  }
});

// ticket_view_component.js

var React = require("react"),
    BackboneModelWatchMixin = require("./mixins/backbone_model_watch_mixin"),
    Ticket = require("./models/ticket");

var MyReactComponent = React.createClass({
  mixins: [BackboneModelWatchMixin],

  propTypes: {
    ticket: React.PropTypes.instanceOf(Ticket).isRequired
  },

  getBackboneModels: function() {
    return [this.props.ticket, this.props.ticket.get("comments")];
  },

  render: function() {
    if (this.props.ticket.isComplete()) {
      return <div>...</div>;
    } else {
      return <div onClick={this.completeTicket}>...</div>;
    }
  },

  completeTicket: function() {
    this.props.ticket.complete();
  }
});

module.exports = MyReactComponent;
/**
* Automatically re-render a React component when one or more backbone
* models emit any events. Automatically binds and unbinds during the normal
* React component lifecycle hooks.
*
* React.createClass({
* mixins: [BackboneModelWatchMixin],
*
* getBackboneModels: function() {
* return [this.props.model, someOtherModel];
* }
* });
*
*/
var _ = require("underscore");
module.exports = {
componentDidMount: function() {
this._watchedBackboneModels = this.getBackboneModels();
_.each(this._watchedBackboneModels, function(model) {
model.on("all", this._doBackboneUpdate);
}, this);
},
componentWillUnmount: function() {
_.each(this._watchedBackboneModels, function(model) {
model.off("all", this._doBackboneUpdate);
}, this);
},
_doBackboneUpdate: function() {
if (this.isMounted()) this.forceUpdate();
},
};
/**
* Easily create a Marionette view that contains a React component and mount/unmount
* it as appropriate in `onShow`/`onClose`.
*
* Marionette.View.extend(ReactComponentView).extend({
* initialize: function(options) {
* this.model = options.model;
* },
*
* getReactComponent: function() {
* return SomeComponent({model: this.model});
* }
* });
*
*/
var React = require("react");
module.exports = {
onShow: function() {
if (this._reactMountEl) {
React.unmountComponentAtNode(this._reactMountEl);
}
this._reactMountEl = this.$el[0];
var component = this.getReactComponent();
React.renderComponent(component, this._reactMountEl);
},
onClose: function() {
if (this._reactMountEl) {
React.unmountComponentAtNode(this._reactMountEl);
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment