通用 React List 组件是否应该从父级接收 props 或 listeners?
Should generic React List component receive props or listeners from parent?
这是一个更 style/theory 的问题,因为我认为这两种方法都可以。场景如下:
我有一个要保持通用的 InfiniteList 组件。它从父级获取所有项目 ID 的当前列表,然后找出它必须实际呈现的项目 ID。为此,我基本上是从列表中提取适当的 ID,然后按 ID 从商店中获取完整数据。
我的问题是:为了保持它的通用性,显然无限列表组件不能真正硬编码它应该从哪个存储中获取完整的项目数据(比如我有 10 种不同类型的项目,它们都有自己的店铺)。但是,对我来说更有意义的是滚动和更改显示的项目集是一种状态。那么,您认为这样做有意义吗:
A) 将 IDS 列表作为 props 传递,以及从父组件传入的 add/remove 侦听器,以便列表组件知道要听谁?
B) 还是只传入列表和 as props 中可用的全套项目数据并让父组件监听适当的商店更有意义?
"listening" 背后的部分动机是,如果商店没有这些项目,它必须获取它们,所以我需要在 itemStore 更新后重新呈现列表。
部分灵感来自这里:ReactJS: Modeling Bi-Directional Infinite Scrolling
我会选择 B,原因如下:
1) 我认为这会产生最通用的组件,因为它不需要知道数据的来源或更新方式。
2) 组件没有状态。
3) 用于侦听 Store 事件和更新组件状态的代码可能太短了,您不会从将其移入组件中享受到太多显着的好处。
我认为 A 的唯一优势是将存储事件处理移至组件中,因此您不必重写它。但是通过这样做,你会强制你的组件有状态。也许在这种情况下,它足够简单并不重要。这真的取决于应用程序。如果层次结构中较高的组件(InfiniteList 的父级)也将重新呈现来自同一商店的事件,我会避免让 InfiniteList 也重新呈现同一事件。如果您是 InfiniteList 是 唯一需要更新该事件的组件,那么在 InfiniteList 中拥有状态可能是有意义的,但这似乎不太可能在所有情况下都成立。因此,我再次倾向于 B,因为它更通用。
话虽这么说,如果你真的想省去重写事件处理逻辑,如果你使用 React 教程中的相同方法,我会利用这个事实并将 Store 本身作为道具传递。在示例中,Stores 是通过继承 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 创建的。例如:
//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
}
});
这显然不如 B 的无状态方法那么通用,实际上只是传递函数本身的一种文体替代方法,但无论哪种方式,我都会使用 propTypes
函数 isRequired
。
这是一个更 style/theory 的问题,因为我认为这两种方法都可以。场景如下:
我有一个要保持通用的 InfiniteList 组件。它从父级获取所有项目 ID 的当前列表,然后找出它必须实际呈现的项目 ID。为此,我基本上是从列表中提取适当的 ID,然后按 ID 从商店中获取完整数据。
我的问题是:为了保持它的通用性,显然无限列表组件不能真正硬编码它应该从哪个存储中获取完整的项目数据(比如我有 10 种不同类型的项目,它们都有自己的店铺)。但是,对我来说更有意义的是滚动和更改显示的项目集是一种状态。那么,您认为这样做有意义吗:
A) 将 IDS 列表作为 props 传递,以及从父组件传入的 add/remove 侦听器,以便列表组件知道要听谁?
B) 还是只传入列表和 as props 中可用的全套项目数据并让父组件监听适当的商店更有意义?
"listening" 背后的部分动机是,如果商店没有这些项目,它必须获取它们,所以我需要在 itemStore 更新后重新呈现列表。
部分灵感来自这里:ReactJS: Modeling Bi-Directional Infinite Scrolling
我会选择 B,原因如下:
1) 我认为这会产生最通用的组件,因为它不需要知道数据的来源或更新方式。
2) 组件没有状态。
3) 用于侦听 Store 事件和更新组件状态的代码可能太短了,您不会从将其移入组件中享受到太多显着的好处。
我认为 A 的唯一优势是将存储事件处理移至组件中,因此您不必重写它。但是通过这样做,你会强制你的组件有状态。也许在这种情况下,它足够简单并不重要。这真的取决于应用程序。如果层次结构中较高的组件(InfiniteList 的父级)也将重新呈现来自同一商店的事件,我会避免让 InfiniteList 也重新呈现同一事件。如果您是 InfiniteList 是 唯一需要更新该事件的组件,那么在 InfiniteList 中拥有状态可能是有意义的,但这似乎不太可能在所有情况下都成立。因此,我再次倾向于 B,因为它更通用。
话虽这么说,如果你真的想省去重写事件处理逻辑,如果你使用 React 教程中的相同方法,我会利用这个事实并将 Store 本身作为道具传递。在示例中,Stores 是通过继承 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 创建的。例如:
//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
}
});
这显然不如 B 的无状态方法那么通用,实际上只是传递函数本身的一种文体替代方法,但无论哪种方式,我都会使用 propTypes
函数 isRequired
。