I would go with B for the following reasons:
1) I think this would result in the most generic Component, because it doesn't need to know anything about where the data is coming from or how it is updated.
2) the Component has no state.
3) the code to listen for Store events and update the Component's state is likely so short you won't enjoy much significant benefit from moving it into the component.
The only advantage I'd see A having is moving that store event handling into the component, so you don't have to rewrite it. But by doing this, you'd force your component to have state. Maybe in this case, it's straightforward enough not matter. It really depends on the application. If components higher up in the hierarchy (parents of the InfiniteList) are also going to re-render on events from the same store, I'd shy away from having InfiniteList also re-render itself on the same event. If you're InfiniteList is the only component that would need to update on that event, then it could make sense to have the state in InfiniteList, but that seems unlikely to hold in all cases. So again, I'd lean toward B as more generic.
That being said, if you really wanted to save rewriting the event handling logic, and if you're using the same approach from the React tutorials, I would leverage this fact and just pass the Store itself as a prop. In the examples, Stores are created by inheriting from EventEmitter.prototype
. If you create each of your Stores this way, you know it will have a addListener()
and removeListener()
, method. Additionally, you could require that each store have the methods getItemIds()
and `getItem( id )'. If you wanted to explicitly enforce that the object passed into your React component has all these methods, you could use propTypes with isRequired. For example:
//YourComponent.js
var YourComponent = React.createClass({
propTypes:{
// assuming ListModel has been defined with the methods you need
listModel: React.PropTypes.instanceOf( ListModel ).isRequired,
// assuming you're using the EventEmitter, like in React example code
modelEvent: React.PropTypes.string.isRequired
},
getInitialState: function(){
// start with an empty array
return { items: [] };
},
componentDidMount: function(){
var evt_handler;
// when the model changes, get the list again
evt_handler = ( function(){
this.setState( { items: this.props.listModel.getItemIds() } );
}.bind( this ) ); // bind to maintain context
// register for events
this.props.listModel.addListener( this.props.modelEvent, evt_handler );
},
render: function(){
...do your filtering, make it pretty
}
});
This is clearly less generic than the stateless approach of B and is really just a stylistic alternative to passing the functions themselves, but either way, I'd use propTypes
with isRequired
for the functions.