我正在搞乱流星中的React。似乎有两种方式来处理事情......
鉴于流星排行榜的例子,我们有一个提供名称和分数的玩家列表。
纯做事方式是获取所有玩家并传递到playersList组件,然后将其分配给playerItem组件。一切都用道具完成,这些模板都是纯粹的。每当玩家改变时,我们可以使用Meteor的反应性来使用React重新渲染所有内容
Tracker.autorun =>
players = Players.find().fetch()
React.render(React.createElement(PlayersList, {players:players}), document.body)
(传递给自动运行的函数将在玩家更改时重新运行)
这正是Pete Hunt在Meteor-React presentation demo中所做的。
现在这样做的另一种方式似乎更有效和细粒度,但不纯粹。那就是将PlayersList组件传递给playerIds列表。将PlayerItem组件传递给playerId并让PlayerItem获取特定玩家并从组件的状态渲染玩家名称和分数。
// inside the PlayerItem component
componentWillMount: =>
Tracker.autorun =>
this.setState('player', Players.findOne(this.props.playerId))
现在PlayerItem 不纯。每当玩家的分数改变时,只有代表该玩家的PlayerItem将被重新渲染。如果我们确保只传递PlayersList的playerId列表,那么只要添加或删除了一个玩家,PlayersList组件就会被重新呈现。
Tracker.autorun =>
playerIds = _.pluck('_id',Players.find({}, {fields:{_id:1}}).fetch())
React.render(React.createElement(PlayersList, {playerIds: playerIds}), document.body)
这是有道理的,因为现在我们对React的渲染周期进行了细粒度的控制,并且当一件事发生变化时,我们不会轰击每个玩家的整个状态。然而,这似乎并不符合React设计的精神。现在我们到处都有内部状态,我们的组件并不纯粹!
我的印象是,React希望我做事的方式是使用全球状态和纯粹的组件,而仅仅依赖于React的和解是超级快速和高效的事实。这让我有点不舒服,因为非纯粹的方式看起来效率更高。
无论如何,我刚开始使用React,所以尽管我阅读了所有文档,但我并不相信我知道我在说什么。所以我想知道 - 我什么时候应该坚持使用纯组件?什么时候可以使用非纯组件?我是否应该在组件中获取数据,还是应该将其作为渲染引擎进行严格反应?
答案 0 :(得分:2)
React.render和在顶级组件中执行它之间的差别很小。无论哪种方式,它都会更新状态或道具,渲染和差异旧/新虚拟dom。
我会让PlayerList获取所有玩家,并将其传递给PlayerItem组件。您应该绑定到componentDidMount
中的外部api,并确保在componentWillUnmount
中取消绑定。 componentWillMount
函数与构造函数具有类似的作用:设置任何非状态实例属性。
PlayerItem应该实现shouldComponentUpdate以提高性能。你有空闲时可以这样做,因为这是一个不影响其余代码的优化。
作为旁注,你可以实现一个有助于流星绑定的mixin。
var MeteorMixin = {
getInitialState: function(){
return this.getUpdatedState();
},
componentDidMount: function(){
this._meteorMixinComputation = Tracker.autorun(function(){
this.setState(this.getUpdatedState());
}.bind(this));
},
componentWillUnmount: function(){
this._meteorMixinComputation.stop();
}
};
然后您的组件将如下所示:
mixins: [MeteorMixin],
getUpdatedState: -> {players: Players.find({}).fetch()}
render: ->
...
免责声明:我不使用流星,所以这可能会有所不同。