反应最佳实践 - 纯或非纯组件?在componentWillMount中获取数据?

时间:2015-02-19 22:02:17

标签: javascript meteor reactjs

我正在搞乱流星中的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,所以尽管我阅读了所有文档,但我并不相信我知道我在说什么。所以我想知道 - 我什么时候应该坚持使用纯组件?什么时候可以使用非纯组件?我是否应该在组件中获取数据,还是应该将其作为渲染引擎进行严格反应?

1 个答案:

答案 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: ->
   ...

免责声明:我不使用流星,所以这可能会有所不同。