Skip to content

Instantly share code, notes, and snippets.

@BinaryMuse
Last active February 1, 2017 00:51
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);
}
}
};
@przeor
Copy link

przeor commented Sep 1, 2016

Hi I see that you use React, so I am sure that you will find interesting the https://reactjs.co - this is the free online convention and tutorial book for React.JS Developers. React is not only the View (in MVC) anymore. ReactJS For Dummies: Why & How to Learn React Redux, the Right Way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment