Javascript React最佳实践--纯组件还是非纯组件?在componentWillMount中获取数据?

Javascript React最佳实践--纯组件还是非纯组件?在componentWillMount中获取数据?,javascript,meteor,reactjs,Javascript,Meteor,Reactjs,我和《流星》里的React混在一起。事情似乎有两种方式 给出流星排行榜的例子,我们有一个球员名单,他们提供了一个名字和分数 纯粹的方法是获取所有玩家并传递到PlayerList组件,然后将其分成playerItem组件。一切都是用道具完成的,这些模板是纯粹的。无论何时玩家改变,我们都可以使用Meteor的反应来用React重新渲染一切 Tracker.autorun => players = Players.find().fetch() React.render(React.cre

我和《流星》里的React混在一起。事情似乎有两种方式

给出流星排行榜的例子,我们有一个球员名单,他们提供了一个名字和分数

纯粹的方法是获取所有玩家并传递到PlayerList组件,然后将其分成playerItem组件。一切都是用道具完成的,这些模板是纯粹的。无论何时玩家改变,我们都可以使用Meteor的反应来用React重新渲染一切

Tracker.autorun =>
  players = Players.find().fetch()
  React.render(React.createElement(PlayersList, {players:players}), document.body)
(传递给自动运行的函数将在玩家更改时重新运行)

这正是皮特·亨特在他的小说中所做的

现在,另一种方法似乎更有效、更细粒度,但不是纯粹的。即向PlayerList组件传递一个PlayerID列表。向PlayerItem组件传递一个playerId,让PlayerItem获取特定的玩家,并从组件的状态呈现玩家名称和分数

// inside the PlayerItem component
componentWillMount: =>
  Tracker.autorun =>
    this.setState('player', Players.findOne(this.props.playerId))
现在PlayerItem不是纯粹的。每当玩家的分数发生变化时,只有代表该玩家的PlayerItem将被重新渲染。如果我们确保仅向PlayerList传递PlayerId列表,那么PlayerList组件将仅在添加或删除玩家时重新呈现

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的协调是超级快速和高效的这一事实。这让我有点不舒服,因为非纯方法似乎更有效


无论如何,我只是从React开始的,所以尽管我阅读了所有的文档,但我不相信我知道我在说什么。所以我想知道——什么时候我应该坚持使用纯组件,什么时候可以使用非纯组件?我应该在组件中获取数据,还是应该严格地将react视为渲染引擎?

react.render与在顶级组件中执行之间几乎没有区别。无论哪种方式,它都会更新状态或道具,渲染和区分旧的/新的虚拟dom

我会让PlayerList获取所有玩家,并将它们传递给playerlistem组件。您应该在
componentDidMount
中绑定到外部API,并确保在
componentWillUnmount
中解除绑定。
componentWillMount
函数的作用与构造函数类似:设置任何非状态实例属性

PlayerItem应实现shouldComponentUpdate以提高性能。您可以在有空闲时间的时候这样做,因为这是一种不会影响其余代码的优化

作为补充说明,您可以实现一个mixin来帮助meteor绑定

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

免责声明:我不使用meteor,所以这可能太离谱了。

。为了澄清一下,你是说我应该使用一个顶级组件来处理状态,而不是全局自动运行。然后我可以做任何事情。设置状态更新我想与流星的反应。但只有顶级组件应该具有状态。PlayerList和PlayerItem都应该是纯的?是的,没错。感谢编辑用户3374348:-)