我正在重写我的应用程序以使用 Flux,但从商店检索数据时遇到问题。我有很多组件,它们嵌套很多。其中一些很大 ( 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>
)
}
});
这种方法的缺点:
- 有 100 多个可能订阅 Store 的组件令人沮丧;
- 很难跟踪数据的更新方式和顺序,因为每个组件都独立检索其数据;
- 即使您可能已经有一个实体处于状态,您也必须将其 ID 传递给孩子,孩子们将再次检索它(否则会破坏一致性)。
所有数据在顶层读取一次并传递给组件
当我厌倦了跟踪错误时,我尝试将所有数据检索放在顶层。然而,这被证明是不可能的,因为对于某些实体,我有多个嵌套级别。
例如:
- A
Category
包含UserAvatar
为该类别做出贡献的人; - 一个
Article
可能有几个Category
s。
因此,如果我想在 an 级别从 Stores 检索所有数据Article
,我需要:
- 从 中检索文章
ArticleStore
; - 从 中检索所有文章的类别
CategoryStore
; - 从 中分别检索每个类别的贡献者
UserStore
; - 以某种方式将所有这些数据传递给组件。
更令人沮丧的是,每当我需要一个深度嵌套的实体时,我都需要在每一层嵌套中添加代码以另外传递它。
加起来
这两种方法似乎都有缺陷。我如何最优雅地解决这个问题?
我的目标:
商店不应该有疯狂的订阅者数量。如果父组件已经这样做了,每个
UserLink
人都听是愚蠢的。UserStore
如果父组件已从存储中检索到某些对象(例如
user
),我不希望任何嵌套组件必须再次获取它。我应该能够通过道具传递它。我不应该在顶层获取所有实体(包括关系),因为这会使添加或删除关系变得复杂。
curator
每次嵌套实体获得新关系(例如,类别获得 a )时,我不想在所有嵌套级别引入新道具。