Skip to content

Instantly share code, notes, and snippets.

@gaearon
Last active January 12, 2018 00:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save gaearon/9724657 to your computer and use it in GitHub Desktop.
Save gaearon/9724657 to your computer and use it in GitHub Desktop.
'use strict';
var Backbone = require('backbone'),
_ = require('underscore');
/**
* A mixin for watching for Backbone models and collections
* Usage:
*
* var SomeComponent = React.createClass({
* mixins: [BackboneMixin],
*
* watchBackboneProps: function (props, listenTo) {
* listenTo(props.someModel, 'change');
* listenTo(props.someCollection, 'add remove change reset');
* },
*
* // this method is optional, implement to improve performance:
* haveBackbonePropsChanged: function (nextProps) {
* return nextProps.someModel !== this.props.someModel ||
* nextProps.someCollection !== this.props.someCollection;
* }
* });
*/
var BackboneMixin = {
componentDidMount: function () {
this._handleBackboneChange = _.throttle(this._handleBackboneChange, 16, {
leading: true,
trailing: true
});
if (!_.isFunction(this.watchBackboneProps)) {
throw new Error('You must provide watchBackboneProps(props, listenTo).');
}
this._bindBackboneEvents(this.props);
},
componentWillReceiveProps: function (nextProps) {
var haveBackbonePropsChanged = true;
if (_.isFunction(this.haveBackbonePropsChanged)) {
haveBackbonePropsChanged = this.haveBackbonePropsChanged(nextProps);
}
if (haveBackbonePropsChanged) {
this._bindBackboneEvents(nextProps);
}
},
componentWillUnmount: function () {
this._unbindBackboneEvents();
},
_bindBackboneEvents: function (props) {
this._unbindBackboneEvents();
var listener = _.extend({}, Backbone.Events),
listenTo = _.partial(listener.listenTo.bind(listener), _, _, this._queueHandleBackboneChange);
this.watchBackboneProps(props, listenTo);
this._backboneListener = listener;
},
_unbindBackboneEvents: function () {
if (this._backboneListener) {
this._backboneListener.stopListening();
delete this._backboneListener;
}
},
_queueHandleBackboneChange: function () {
_.defer(this._handleBackboneChange);
},
_handleBackboneChange: function () {
if (this.isMounted()) {
this.forceUpdate();
}
}
};
module.exports = BackboneMixin;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment