我试图尽可能地坚持Flux模式,但我必须遗漏一些东西,因为我无法想象如何在不使用hack或做出错误的模式的情况下让它工作。
我有一个由大量数据分段的应用程序。让我们说它是一个资源管理应用程序,公司的每个部门都有不同的资源集。该应用程序的用户将始终访问他们所属的任何部门,并留在那里。有些人可能有他们管理的多个部门。
因此,在此应用程序的顶部,将有一种方法可以选择您正在使用的部门。
这里的关键是,在部门列表加载之前,我无法显示任何有用的内容,而且我已选择要显示的部门(目前只是列表中的第一项)。
要实现此目的,应用程序的根组件会查看DepartmentStore以确定它当前是否正在加载。如果它正在加载,它甚至不会打扰渲染组件。像这样:
function initApp(projectSlug) {
// prefetch some data!
DeptActions.getAll();
}
function getStateFromStores() {
return {
loading: DeptStore.getLoading()
};
}
export default React.createClass({
getInitialState: function() {
return getStateFromStores();
},
componentDidMount: function() {
initApp();
DeptStore.addChangeListener(this._deptChange);
},
componentWillUnmount: function() {
DeptStore.removeChangeListener(this._deptChange);
},
_deptChange: function() {
this.setState(getStateFromStores());
},
render: function() {
return (
this.state.projectsLoading
? <div>Loading...</div>
: (<div>
<Header/>
<div className="body-content">
<div className="grid-container">
{this.props.children}
</div>
</div>
<Footer/>
</div>)
);
}
});
props.children将是React Router指定的任何组件。
这样,页面的实际组件可以呈现并理所当然地认为所有部门都已加载,并且已经设置了“当前”部门。
问题是组件一旦呈现,就需要开始加载部门的资源。为了开始这个过程,它会在安装时启动一个动作:
componentDidMount: function(){
ResourceActions.getResources();
},
此操作将启动一个API调用,该调用使用DeptStore的当前部门来了解要加载的内容。然后它调度一个RESOURCE_LOADING事件,也许你可以猜测,它失败了,因为:
Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch.
这是因为基本上,部门加载的操作会导致资源组件呈现,这会尝试启动资源获取操作。一个动作导致另一个动作。
关于此类问题的所有示例和类似问题对我来说都不尽如人意。例如:
Flux Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch
a scenario flux doesn't support
即使是来自Facebook的Todo列表和Chat App示例也没有解决这个问题。 Todo列表甚至没有加载的“初始”数据。聊天应用程序可以,但它只是在应用程序启动时加载所有消息。
我无法在应用启动时加载资源,因为我必须首先知道哪个部门。即使我以某种方式知道这一点,我也不想加载资源,除非资源组件需要它们。用户可能在当前部门的其他页面上,而不显示资源。因此,以某种方式加载资源以响应原始的Dept更改事件对我来说也不可行。
请帮助我获得解决此问题的缺点? :)我如何将Departments列表分开,然后加载Resources以响应Departments的加载,并执行它以便它以某种方式由组件驱动,这样我就不会进行昂贵的Resources API调用,除非页面上的组件需要吗?
答案 0 :(得分:2)
正如其他帖子中的答案所指出的,这是助焊剂模式解决方案中的一个缺点/漏洞。唯一的解决方法(类似于之前的答案)是从顶部组件中的componentDidMount()
和componentDidUpdate()
创建一个调用,其执行类似的操作:
checkAndFetchResources: function() {
if (this.props.resourcesToRender != undefined) {
ResourceActions.getResources();
}
}
将作为props获取的资源传递给资源组件。 这样,在上一轮调度之后调用您的获取操作,然后渲染周期完全结束。
这与之前提供的答案类似,因此可能不适合您(正如您在问题中所述)。在这种情况下,进一步澄清为什么答案不符合您的需求会有所帮助。