Tôi đang viết lại ứng dụng của mình để sử dụng Flux và tôi gặp sự cố khi truy xuất dữ liệu từ Stores. Tôi có rất nhiều thành phần, và chúng lồng vào nhau rất nhiều. Một số trong số chúng lớn ( Article
), một số nhỏ và đơn giản ( UserAvatar
, UserLink
).
Tôi đang đấu tranh với việc tôi nên đọc dữ liệu từ các Cửa hàng ở đâu trong hệ thống phân cấp thành phần.
Tôi đã thử hai cách tiếp cận cực đoan, cả hai đều không thích:
Tất cả các thành phần thực thể đọc dữ liệu của riêng chúng
Mỗi thành phần cần một số dữ liệu từ Store chỉ nhận ID thực thể và tự truy xuất thực thể.
Ví dụ, Article
được thông qua articleId
, UserAvatar
và UserLink
được thông qua userId
.
Cách tiếp cận này có một số nhược điểm đáng kể (được thảo luận dưới mẫu mã).
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>
)
}
});
Nhược điểm của phương pháp này:
- Thật khó chịu khi có các thành phần 100 có khả năng đăng ký Cửa hàng;
- Thật khó để theo dõi dữ liệu được cập nhật như thế nào và theo thứ tự nào vì mỗi thành phần lấy dữ liệu của nó một cách độc lập;
- Mặc dù bạn có thể đã có một thực thể ở trạng thái, bạn buộc phải chuyển ID của nó cho trẻ em, những người này sẽ truy xuất lại nó (hoặc nếu không sẽ phá vỡ tính nhất quán).
Tất cả dữ liệu được đọc một lần ở cấp cao nhất và được chuyển đến các thành phần
Khi tôi mệt mỏi với việc theo dõi lỗi, tôi đã cố gắng đặt tất cả dữ liệu truy xuất ở cấp cao nhất. Tuy nhiên, điều này được chứng minh là không thể vì đối với một số thực thể, tôi có một số cấp độ lồng vào nhau.
Ví dụ:
- A
Category
chứaUserAvatar
những người đóng góp cho danh mục đó; - An
Article
có thể có một sốCategory
s.
Do đó, nếu tôi muốn truy xuất tất cả dữ liệu từ Cửa hàng ở cấp độ an Article
, tôi cần phải:
- Lấy bài báo từ
ArticleStore
; - Truy xuất tất cả các danh mục của bài viết từ
CategoryStore
; - Truy xuất riêng từng cộng tác viên của danh mục từ
UserStore
; - Bằng cách nào đó, truyền tất cả dữ liệu đó xuống các thành phần.
Đáng buồn hơn nữa, bất cứ khi nào tôi cần một thực thể lồng nhau sâu sắc, tôi sẽ cần thêm mã vào mỗi cấp độ lồng để bổ sung chuyển nó xuống.
Tổng hợp
Cả hai cách tiếp cận đều có vẻ thiếu sót. Làm cách nào để giải quyết vấn đề này một cách thanh lịch nhất?
Mục tiêu của tôi:
Các cửa hàng không nên có số lượng người đăng ký quá lớn. Thật ngu ngốc cho mỗi người
UserLink
ngheUserStore
nếu các thành phần cha đã làm điều đó.Nếu thành phần mẹ đã truy xuất một số đối tượng từ cửa hàng (ví dụ
user
), tôi không muốn bất kỳ thành phần lồng nhau nào phải tìm nạp lại. Tôi sẽ có thể vượt qua nó thông qua đạo cụ.Tôi không cần phải tìm nạp tất cả các thực thể (bao gồm cả các mối quan hệ) ở cấp cao nhất vì việc thêm hoặc xóa các mối quan hệ sẽ phức tạp. Tôi không muốn giới thiệu các đạo cụ mới ở tất cả các cấp lồng nhau mỗi khi một thực thể lồng nhau nhận được một mối quan hệ mới (ví dụ: danh mục nhận được a
curator
).