handling backbone model/collection changes in react.js handling backbone model/collection changes in react.js reactjs reactjs

handling backbone model/collection changes in react.js


Instead of manually binding event listeners, you can use a mixin based on this BackboneMixin to help automatically bind and unbind the listeners:

https://github.com/facebook/react/blob/1be9a9e/examples/todomvc-backbone/js/app.js#L148-L171

Then you simply write

var List = React.createClass({    mixins: [BackboneMixin],    getBackboneModels: function() {        return [this.props.myCollection];    },    render: function(){        var listItems = this.props.myCollection.map(function(item){            return <li>{item.get("someAttr")}</li>;        });        return <ul>{listItems}</ul>;    }});

and the component will be rerendered when anything changes in the collection. You only need to put BackboneMixin on the top-level component -- any descendants will be rerendered automatically at the same time.


IMO, React is still very new and there are very few established rules on how to work with data and reactive models like Backbone. This is also a strength, if you have an existing application - react can be integrated on some smaller parts of it without redefining the entire data flow.

I believe that since React can call render "smart" at any time – that is only re-rendering parts that have changed – you don’t really need to pass data as states. Just pass the data, add listeners on the top component and call forceUpdate when the model has changed and it will propagate down nicely.

It just seems more "right" to pass backbone models as props, not states.

One important thing that I learned the hard way is to use the model.cid as key (and not Math.random()) when rendering backbone model lists:

var listItems = this.props.myCollection.map(function(item){    return <li key={item.cid}>{item.get("someAttr")}</li>;});

Because otherwise React won’t be able to recognize what model to re-render because all of them will have new keys on each render.


I had been playing around with the BackboneMixin mentioned here and a couple other react resources (of the limited info currently out there). I found that when I was listening to a collection that was being updated from the server, just as many n 'add' events are going to be triggered on the collection and listened to by the BackboneMixin, thus calling force update n number of times, which calls render and whatever is called from render n number of times.

Instead, I used underscore/lo-dash's throttle method to limit the number of times forceUpdate would be called. At the very least this has limited the render method from being called so much. I know react isn't actually doing any DOM manipulation there, and its just a virtual DOM, but still there is no reason it should be called 100 times for 100 immediate additions to a Collection.

So my solution looks like https://gist.github.com/ssorallen/7883081 but with the componentDidMount method like this instead:

componentDidMount: function() {  //forceUpdate will be called at most once every second  this._boundForceUpdate = _.throttle(this.forceUpdate.bind(this, null), 1000);  this.getBackboneObject().on("all", this._boundForceUpdate, this);}