Flux を使用するようにアプリを書き直していますが、ストアからのデータの取得に問題があります。たくさんのコンポーネントがあり、それらはたくさん入れ子になっています。大きいもの ( Article
) もあれば、小さくてシンプルなもの ( UserAvatar
、UserLink
) もあります。
コンポーネント階層のどこでストアからデータを読み取る必要があるかで苦労しています。
私は 2 つの極端なアプローチを試みましたが、どちらもあまり好きではありませんでした。
すべてのエンティティ コンポーネントが独自のデータを読み取ります
Store からのデータを必要とする各コンポーネントは、エンティティ ID だけを受け取り、独自にエンティティを取得します。
たとえば、Article
is passed articleId
、UserAvatar
およびUserLink
are passeduserId
です。
このアプローチには、いくつかの重大な欠点があります (コード サンプルで説明します)。
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>
)
}
});
このアプローチの欠点:
- 何百ものコンポーネントがストアにサブスクライブする可能性があるのはイライラします。
- 各コンポーネントが個別にデータを取得するため、データがどのように更新され、どのような順序で更新されるかを追跡することは困難です。
- 状態のエンティティが既にある場合でも、その ID を子に渡す必要があり、子はエンティティを再度取得します (または、一貫性を破ります)。
すべてのデータは最上位で一度読み取られ、コンポーネントに渡されます
バグの追跡にうんざりしていたとき、すべてのデータ取得を最上位にしようとしました。ただし、エンティティによっては複数レベルのネストがあるため、これは不可能であることが判明しました。
例えば:
- Aには、そのカテゴリに貢献する s 人の人が
Category
含まれます。UserAvatar
- An
Article
には複数Category
の が含まれる場合があります。
したがって、ストアから のレベルですべてのデータを取得する場合はArticle
、次のようにする必要があります。
- から記事を取得し
ArticleStore
ます。 - からすべての記事のカテゴリを取得し
CategoryStore
ます。 - から各カテゴリの貢献者を個別に取得します
UserStore
。 - どういうわけか、そのすべてのデータをコンポーネントに渡します。
さらに苛立たしいことに、深くネストされたエンティティが必要な場合は常に、ネストの各レベルにコードを追加して、それをさらに渡す必要があります。
まとめ
どちらのアプローチにも欠陥があるようです。この問題を最もエレガントに解決するにはどうすればよいですか?
私の目的:
ストアには、非常識な数の加入者がいるべきではありません。親コンポーネントがすでにそれを行っている場合、それぞれ
UserLink
がリッスンするのはばかげています。UserStore
親コンポーネントがストアから何らかのオブジェクトを取得した場合 (例:
user
)、ネストされたコンポーネントがそれを再度取得する必要はありません。私は小道具を介してそれを渡すことができるはずです。リレーションシップの追加や削除が複雑になるため、すべてのエンティティ (リレーションシップを含む) をトップ レベルでフェッチする必要はありません。ネストされたエンティティが新しい関係を取得するたびに、すべてのネスト レベルで新しい props を導入したくありません (たとえば、カテゴリが を取得します
curator
)。