我有一个包含多个视图的反应应用程序(例如Profile
,Followers
)。这些视图中的每一个当前都是它自己的React组件,它在服务器端和客户端都执行。我开始努力理解构造代码的正确方法。
例如,假设已加载Profile
并且用户点击“查看关注者”。此时,将向调度程序发送一条消息gotoFollowers
。在顶层,我们然后渲染一个全新的React组件(即Followers
组件)。不幸的是,Follower
和Profile
组件都需要类似的数据(例如会话数据,用户照片,用户名,甚至是关注者,因为我们在Profile
上显示了一小部分关注者)。因此,每次用户更改页面时,必须在顶层重新渲染(包括执行ajax调用)是非常浪费的。
我认为我没有正确地做到这一点。我应该使用单亲React组件吗? (我也看到了问题)我应该如何构建具有许多视图的大型React应用程序?
window.render = function (page, id, pushState) {
var stateURL = '';
switch (page) {
case 'Profile':
stateURL = '/' + id;
async.parallel({
profileData: function (callback) { MemberLoader.load(id, callback); },
followerData: function (callback) { FollowerLoader.load(id, callback); },
},
sessionData: function (callback) { Session.get(callback); },
}, function (err, results) {
var component = React.createFactory(Profile);
React.render(component({ member: results.profileData, followers: results.followerData, session: results.sessionData }), mountNode);
});
break;
case 'Followers':
stateURL = '/' + id + '/followers';
async.parallel({
profileData: function (callback) { MemberLoader.load(id, callback); },
sessionData: function (callback) { Session.get(callback); },
followerData: function (callback) { FollowerLoader.load(id, callback); },
}, function (err, results) {
var component = React.createFactory(Followers);
React.render(component({ member: results.profileData, followers: results.followerData, session: results.sessionData }), mountNode);
});
break;
};
if (pushState) {
window.history.pushState({ page: page, id: id }, null, stateURL);
} else {
window.history.replaceState({ page: page, id: id }, null, stateURL);
}
};
Dispatcher.register(function(event) {
if (event.action === 'gotoProfile') {
window.render('Profile', event.username, true);
}
else if (event.action === 'gotoFollowers') {
window.render('Followers', event.username, false);
}
});
注意:我们的应用程序在服务器端和客户端都呈现。
答案 0 :(得分:0)
要解决多次获取相同数据的问题,您应该查看Promises - 这可能会替换您正在使用的async
库。
Promises允许您进行一次异步调用,但即使在成功调用之后也会附加回调。您可以保留对承诺的引用,并在以后的应用程序中使用它 - 而无需检查承诺是否已经解决。
我在下面为你准备了一个(未经测试的)示例实现 - 它做了几件事。
async.parallel
代码替换为Promise.all
,这会创建一个新的承诺,在成功解决所有已通过的承诺后解析。React.render
置于对then
的承诺中 - 只有在所有异步调用完成后才会调用它。见下文:
var profilePromise;
var followerPromise;
var sessionPromise;
var getProfilePromise = function(){
//If the profile promise already exists (ie, the async call has already been started)
//then we return the promise, otherwise we make the async call.
if(!profilePromise){
profilePromise = new Promise(function(resolve, reject){
MemberLoader.load(id, function(){
//Depending on the result you either call `resolve` and pass
//in the data, or call `reject` with the error
});
});
}
return profilePromise;
};
//Repeat a version of the above function for your follower and session promise
window.render = function (page, id, pushState) {
var stateURL = '';
switch (page) {
case 'Profile':
stateURL = '/' + id;
Promise.all([
getProfilePromise(),
getFollowerPromise(),
getSessionPromise()
]).then(function(results){
var component = React.createFactory(Profile);
React.render(component({ member: results[0], followers: results[1], session: results[2] }), mountNode);
}).catch(function(err){
/** handle errors here */
});
break;
case 'Followers':
stateURL = '/' + id + '/followers';
Promise.all([
getProfilePromise(),
getFollowerPromise(),
getSessionPromise()
]).then(function(results) {
var component = React.createFactory(Followers);
React.render(component({ member: results[0], followers: results[1], session: results[2] }), mountNode);
}).catch(function(err){
/** handle errors here */
});
break;
}
if (pushState) {
window.history.pushState({ page: page, id: id }, null, stateURL);
} else {
window.history.replaceState({ page: page, id: id }, null, stateURL);
}
};