我有一个具有多个 View 的 React 应用程序(例如 Profile
、Followers
)。这些 View 中的每一个目前都作为它自己的 React 组件存在,该组件在服务器端和客户端执行。我开始努力理解构建代码的正确方法。
例如,假设 Profile
已加载并且用户单击“查看关注者”。那时,调度员收到一条消息,内容为 gotoFollowers
。然后在顶层渲染一个全新的 React 组件(即 Followers
组件)。不幸的是,Follower
和 Profile
组件都需要类似的数据(例如 session 数据、用户照片、用户名,甚至还有关注者,因为我们在 上显示了关注者的片段>简介
)。因此,每次用户更改页面时都必须在顶层重新呈现(包括执行 ajax 调用)感觉非常浪费。
我假设我做的不正确。我应该使用单父 React 组件吗? (我也看到了问题)我应该如何构建具有多个 View 的大型 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);
}
});
注意:我们的应用程序同时在服务器端和客户端呈现。
最佳答案
要解决多次获取相同数据的问题,您应该查看Promises - 这可以替换您现在使用的 async
库。
Promises 允许您进行一次异步调用,但即使在调用成功后也会附加回调。您可以维护对 promise 的引用并稍后在您的应用程序中使用它 - 无需检查 promise 是否已经解决。
我在下面为您整理了一个(未经测试的)示例实现 - 它做了几件事。
- 为您的每个数据存储创建对 promise 的引用
- 创建一个方法,如果尚未进行异步调用,则返回该调用,然后返回该 promise
- 将您的
async.parallel
代码替换为Promise.all
,这会创建一个新的 promise,当所有传递的 promise 都已成功解析时,该 promise 将被解析。 - 将你的
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);
}
};
关于javascript - 高效构建具有多个 View 的大型 React.js 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29649272/