最佳答案
我重写我的应用程序使用通量和我有一个问题,检索数据从商店。我有很多组件,它们有很多巢。它们有的大(Article
) ,有的小而简单(UserAvatar
,UserLink
)。
我一直在纠结在组件层次结构中我应该在哪里读取来自 Stores 的数据。
我尝试了两种极端的方法,两种我都不太喜欢:
每个需要从 Store 获得一些数据的组件只接收实体 ID,并自行检索实体。
例如,Article
被传递 articleId
,UserAvatar
和 UserLink
被传递 userId
。
这种方法有几个明显的缺点(在代码示例中讨论)。
var Article = React.createClass({
mixins: [createStoreMixin(ArticleStore)],
propTypes: {
articleId: PropTypes.number.isRequired
},
getStateFromStores() {
return {
article: ArticleStore.get(this.props.articleId);
}
},
render() {
var article = this.state.article,
userId = article.userId;
return (
<div>
<UserLink userId={userId}>
<UserAvatar userId={userId} />
</UserLink>
<h1>{article.title}</h1>
<p>{article.text}</p>
<p>Read more by <UserLink userId={userId} />.</p>
</div>
)
}
});
var UserAvatar = React.createClass({
mixins: [createStoreMixin(UserStore)],
propTypes: {
userId: PropTypes.number.isRequired
},
getStateFromStores() {
return {
user: UserStore.get(this.props.userId);
}
},
render() {
var user = this.state.user;
return (
<img src={user.thumbnailUrl} />
)
}
});
var UserLink = React.createClass({
mixins: [createStoreMixin(UserStore)],
propTypes: {
userId: PropTypes.number.isRequired
},
getStateFromStores() {
return {
user: UserStore.get(this.props.userId);
}
},
render() {
var user = this.state.user;
return (
<Link to='user' params={{ userId: this.props.userId }}>
{this.props.children || user.name}
</Link>
)
}
});
这种做法的缺点是:
当我厌倦了追踪 bug 时,我试图把所有的数据检索放在顶层。然而,事实证明这是不可能的,因为对于某些实体,我有几个嵌套级别。
例如:
Category
包含对该类别有贡献的人的 UserAvatar
;Article
可能有几个 Category
。因此,如果我想在 Article
级别从 Stores 检索所有数据,我需要:
ArticleStore
中检索文章;CategoryStore
中检索所有文章的类别;UserStore
中检索每个类别的贡献者;更令人沮丧的是,无论何时我需要一个深度嵌套的实体,我都需要向每个嵌套级别添加代码来额外地传递它。
这两种方法似乎都有缺陷。我如何最优雅地解决这个问题?
我的目标:
商店不应该有这么多疯狂的用户。如果父组件已经在监听 UserStore
,那么每个 UserLink
监听 UserStore
就是愚蠢的。
如果父组件已经从存储中获取了一些对象(例如 user
) ,我不希望任何嵌套组件必须再次获取它。我应该可以通过道具传球。
我不应该必须在顶层获取所有实体(包括关系) ,因为这会使添加或删除关系变得复杂。我不想在每次嵌套实体得到一个新的关系时(例如,分类得到一个 curator
)在所有嵌套级别引入新的道具。