处理react.js中的主干模型/集合更改

Mar*_*pse 32 javascript backbone.js reactjs

在过去的几周里,我一直在使用facebooks框架React.js和Backbone一起工作.当Backbone集合发生变化时,我仍然不能完全确定重新渲染React组件的最佳方法是什么已作为道具传入.

目前我所做的是在componenentWillMount集合上设置change/add/remove监听器并在触发时设置状态:

componentWillMount: function(){
    var myCollection = this.props.myCollection;
    var updateState = function(){
        this.setState({myCollection: myCollection.models});
    }

    myCollections.on("add remove", updateState, this);
    updateState();
}

render: function(){
    var listItems = this.state.myCollection.map(function(item){
        return <li>{item.get("someAttr")}</li>;
    });
    return <ul>{listItems}</ul>;
}
Run Code Online (Sandbox Code Playgroud)

我已经看到了将模型克隆到状态的示例:

var updateState = function () {
    this.setState({ myCollection: _.clone(this.myCollection.models) });
};
Run Code Online (Sandbox Code Playgroud)

我也看到过变体,其中props中的模型/集合直接用于渲染而不是使用状态,然后在集合/模型更改时调用forceUpdate,导致组件重新渲染

componentWillMount: function(){
    var myCollection = this.props.myCollection;
    myCollections.on("add remove", this.forceUpdate, this);
}

render: function(){
    var listItems = this.props.myCollection.map(function(item){
        return <li>{item.get("someAttr")}</li>;
    });
    return <ul>{listItems}</ul>;
}
Run Code Online (Sandbox Code Playgroud)

不同的方法有哪些好处和缺点?有没有办法做到这就是The React方式

Sop*_*ert 12

您可以使用基于此BackboneMixin的mixin来帮助自动绑定和取消绑定侦听器,而不是手动绑定事件侦听器:

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

然后你就写了

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>;
    }
});
Run Code Online (Sandbox Code Playgroud)

当集合中的任何更改时,组件将被重新呈现.您只需要将BackboneMixin放在顶级组件上 - 任何后代将同时自动重新呈现.


Dav*_*ing 10

IMO,React仍然非常新,关于如何使用Backbone等数据和反应模型的规则很少.如果您有一个现有的应用程序,这也是一个优势 - 可以将反应集成到它的一些较小部分,而无需重新定义整个数据流.

我相信,因为React可以在任何时候调用渲染"智能" - 这只是重新渲染已经改变的部分 - 你真的不需要将数据作为状态传递.只需传递数据,在顶部组件上添加侦听器,并forceUpdate在模型发生更改时调用它,它将很好地传播下来.

将骨干模型作为道具而不是状态传递似乎更"正确".

我学到很难的一件重要事情是在渲染骨干模型列表时使用model.cidas键(而不是Math.random()):

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

因为否则React将无法识别要重新渲染的模型,因为所有模型都会在每个渲染上都有新的键.


duh*_*koh 5

我一直在玩这里提到的BackboneMixin和其他一些反应资源(目前有限的信息).我发现当我正在收听从服务器更新的集合时,就会在集合上触发多个n'add'事件并由BackboneMixin监听,因此调用force update n次,它调用渲染和从渲染n次调用的任何东西.

相反,我使用下划线/ lo-dash的节流方法来限制forceUpdate的调用次数.至少这限制了渲染方法被调用这么多.我知道react实际上并没有在那里进行任何DOM操作,它只是一个虚拟DOM,但仍然没有理由它应该被100次调用100次立即添加到Collection.

所以我的解决方案看起来像https://gist.github.com/ssorallen/7883081但是使用了像这样的componentDidMount方法:

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);
}
Run Code Online (Sandbox Code Playgroud)