Open lynnaloo opened 10 years ago
The backbone mixin is deprecated for essentially the reason you mention - any change on the model causes a forceUpdate
on the component.
Internally we do have a version that uses state. It requires a bit more configuration because you have to tell it how to update state when the model changes, but I think that tradeoff is well worth it. I don't think it's gotten much use since we're gradually moving away from backbone backing our views to simple objects / flux.
I'll leave this open until I add a note about this.
This is the mixin we used (until we transitioned to Flux as well):
'use strict';
var Backbone = require('backbone'),
_ = require('underscore');
var BackboneStateMixin = {
getInitialState: function () {
if (_.isFunction(this.getBackboneState)) {
return this.getBackboneState(this.props);
} else {
return {};
}
},
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()) {
return;
}
if (_.isFunction(this.getBackboneState)) {
this.setState(this.getBackboneState(this.props));
} else {
this.forceUpdate();
}
}
};
module.exports = BackboneStateMixin;
Components define watchBackboneProps(props, listenTo)
, getBackboneState(props)
, optionally haveBackbonePropsChanged(nextProps)
.
If the backbone-mixin is deprecated, then what are you using in it's place? I'm not sure if this is part of what was abandoned, but I'm wondering in the example why the Backbone model is a prop instead of in the state? Doesn't that force you to have to
setProps
on the parent andforceUpdate
on the component?