Skip to content
This repository has been archived by the owner on May 15, 2019. It is now read-only.

backbone-mixin #19

Open
lynnaloo opened this issue Sep 18, 2014 · 2 comments
Open

backbone-mixin #19

lynnaloo opened this issue Sep 18, 2014 · 2 comments

Comments

@lynnaloo
Copy link

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 and forceUpdate on the component?

@joelburget
Copy link
Contributor

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.

@gaearon
Copy link

gaearon commented Oct 15, 2014

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).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants