如何在 Flux 中加载初始数据,但前提是组件需要它
Posted
技术标签:
【中文标题】如何在 Flux 中加载初始数据,但前提是组件需要它【英文标题】:How to load initial data in Flux, but only if a component needs it 【发布时间】:2016-01-11 20:56:48 【问题描述】:我正在尽我所能坚持 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 列表甚至没有加载的“初始”数据。聊天应用可以,但它只是在应用启动时加载所有消息。
应用启动时我无法加载资源,因为我必须先知道哪个部门。即使我知道这一点,我也不想加载资源,除非资源组件需要它们。用户可能在当前部门的其他页面上,这些页面不显示资源。因此,以某种方式加载资源以响应原始部门更改事件对我来说也不可行。
请帮助我获得解决此问题所需的见解? :) 我如何保持部门列表分开,然后加载资源以响应部门加载,并这样做以便它以某种方式由组件驱动,这样我就不会进行昂贵的资源 API 调用,除非页面上的组件需要吗?
【问题讨论】:
【参考方案1】:正如其他帖子中的答案所指出的,这是通量模式解决方案中的一个缺点/漏洞。唯一的解决方法(类似于以前的答案)是在顶部组件中创建来自 componentDidMount()
和 componentDidUpdate()
的调用,它执行以下操作:
checkAndFetchResources: function()
if (this.props.resourcesToRender != undefined)
ResourceActions.getResources();
并将获取的资源作为道具传递给资源组件。 这样一来,您的 fetch 操作会在上一轮调度和渲染周期完全完成后调用。
这与之前提供的答案类似,因此对您来说可能还不够(正如您在问题中所述)。在这种情况下,进一步澄清为什么这些答案不符合您的需求会有所帮助。
【讨论】:
以上是关于如何在 Flux 中加载初始数据,但前提是组件需要它的主要内容,如果未能解决你的问题,请参考以下文章
在 Spring Boot 应用程序上使用 Flyway 时如何在 H2 中加载初始数据?
如何通过Spring Boot在MongoDB中加载初始数据?