如何在 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中加载初始数据?

如何使用角度6的分页,过滤,排序功能在表组件中加载大数据

fluent 中加载heat flux 用啥宏,是define boundary 的宏么?谢谢

如何在 MongoDB 中加载初始数据?

如何在 FMX 组件中加载资源