Saya menulis ulang aplikasi saya untuk menggunakan Flux dan saya memiliki masalah dengan mengambil data dari Toko. Saya memiliki banyak komponen, dan mereka banyak bersarang. Beberapa di antaranya besar ( Article
), beberapa kecil dan sederhana ( UserAvatar
, UserLink
).
Saya telah berjuang dengan di mana dalam hierarki komponen saya harus membaca data dari Toko.
Saya mencoba dua pendekatan ekstrim, yang tidak satu pun yang saya sukai:
Semua komponen entitas membaca datanya sendiri
Setiap komponen yang membutuhkan beberapa data dari Store hanya menerima ID entitas dan mengambil entitasnya sendiri.
Misalnya, Article
dilewatkan articleId
, UserAvatar
dan UserLink
dilewatkan userId
.
Pendekatan ini memiliki beberapa kelemahan signifikan (dibahas di bawah contoh kode).
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>
)
}
});
Kerugian dari pendekatan ini:
- Sungguh membuat frustrasi memiliki 100-an komponen yang berpotensi berlangganan Toko;
- Ini sulit untuk melacak bagaimana data diperbarui dan dalam rangka apa karena masing-masing komponen mengambil data secara independen;
- Meskipun Anda mungkin sudah memiliki entitas dalam status, Anda terpaksa meneruskan ID-nya kepada anak-anak, yang akan mengambilnya lagi (atau merusak konsistensi).
Semua data dibaca sekali di tingkat teratas dan diteruskan ke komponen
Ketika saya lelah melacak bug, saya mencoba menempatkan semua pengambilan data di tingkat atas. Ini, bagaimanapun, terbukti tidak mungkin karena untuk beberapa entitas saya memiliki beberapa tingkat bersarang.
Sebagai contoh:
- A
Category
berisiUserAvatar
orang yang berkontribusi pada kategori itu; - Sebuah
Article
mungkin memiliki beberapaCategory
s.
Oleh karena itu, jika saya ingin mengambil semua data dari Toko di tingkat Article
, saya perlu:
- Ambil artikel dari
ArticleStore
; - Ambil semua kategori artikel dari
CategoryStore
; - Ambil secara terpisah setiap kontributor kategori dari
UserStore
; - Entah bagaimana meneruskan semua data itu ke komponen.
Yang lebih membuat frustrasi, setiap kali saya membutuhkan entitas yang sangat bersarang, saya perlu menambahkan kode ke setiap tingkat bersarang untuk meneruskannya.
Menyimpulkan
Kedua pendekatan tersebut tampaknya cacat. Bagaimana cara mengatasi masalah ini dengan paling elegan?
Tujuan saya:
Toko seharusnya tidak memiliki jumlah pelanggan yang gila-gilaan. Itu bodoh bagi masing-masing
UserLink
untuk mendengarkanUserStore
jika komponen induk sudah melakukan itu.Jika komponen induk telah mengambil beberapa objek dari penyimpanan (misalnya
user
), saya tidak ingin komponen bersarang harus mengambilnya lagi. Saya harus bisa meneruskannya melalui alat peraga.Saya tidak perlu mengambil semua entitas (termasuk hubungan) di tingkat atas karena akan mempersulit penambahan atau penghapusan hubungan. Saya tidak ingin memperkenalkan properti baru di semua level bersarang setiap kali entitas bersarang mendapat hubungan baru (misalnya kategori mendapat a
curator
).