如何保留本地组件数据,例如微调器/错误,在 Flux 商店之外?

Posted

技术标签:

【中文标题】如何保留本地组件数据,例如微调器/错误,在 Flux 商店之外?【英文标题】:How to keep local component data , e.g. spinners/errors, outside of Flux stores? 【发布时间】:2015-09-03 08:00:19 【问题描述】:

注意:我使用 Reflux 作为我的 Flux 库,因此示例将使用它的语法。然而,这个问题一般适用于 Flux。

在我的 Flux 示例应用程序中,我有一个 productStore.js 文件,它保存系统中产品的状态并监听各种产品管理操作,例如 REMOVE_PRODUCTADD_PRODUCT

这是商店中的示例数据:


    products: [
        
            productName: "A"
        ,
        
            productName: "B"
        
    ]

现在我想向组件添加一个REFRESH_PRODUCTS 操作。

调用看起来像这样:

component.jsx

onRefresh(e) 
    actions.refreshProducts();

由于刷新产品是一个异步操作,我想在它继续时显示微调器,如果它失败则显示错误。显而易见的 Flux 方法是将加载状态和产生的错误(如果发生这种情况)添加到存储中,如下所示:

productStore.js

onRefreshProducts() 

    logger.info("Logging in:", email);
    this.storeData.inProgress = true;
    this.storeData.error = null;
    this.trigger(this.data);

    api.getProducts()
        .then((response) => 
            this.storeData.products = response.data.products;
        )
        .catch((response) => 
            this.storeData.error = error;
        )
        .then(() => 
            this.storeData.inProgress = false;
            this.trigger(this.data);
        );

现在数据的存储变得很脏,带有各种标志:


    inProgress: false,
    error: null,

    products: [
        
            productName: "A"
        ,
        
            productName: "B"
        
    ]

如果多个组件需要查看产品加载的进度或刷新失败,这种状态对我来说非常好,但以防万一,没有其他组件需要这种信息。所以感觉我在没有充分理由的情况下将私有数据置于全局状态。

我希望能够做这样的事情:

component.jsx - 错误代码

onRefresh(e) 

    this.setState(error: false, inProgress: true);
    actions.refreshProducts()
        .catch(function(err) 
            this.setState(error: err);
        )
        .then(function() 
            this.setState(inProgress: false);
        );

然后我可以保持 store 的代码干净。但是,我没有明显的方法来做到这一点 - 根据设计,操作创建了一个不允许从操作返回数据的分隔。

正确的方法是什么?如何在将相关数据保持在全局状态之外的同时执行私有微调器/错误/等?

【问题讨论】:

为什么不把它设置在组件的状态上,而不是在商店里呢?像往常一样使用 setState()。如果我正确理解您的问题 - 对于页面范围的状态,我使用商店 - 对于特定于组件的状态,我只是将其存储在那里。 因为商品数据应该在商店中。所以我确实想更新商店。我只想将进程的进度/错误处理保留在组件内。 【参考方案1】:

这是我在写这个问题时想到的一个解决方案:

在商店中创建一个允许通过参数更新产品数据的新操作,例如:refreshProductFromData 直接从组件调用 API 在组件中操作微调器/错误处理 通过新操作将从 API 检索到的数据传递到商店

像这样:

component.jsx

onRefresh(e) 

    this.setState(error: false, inProgress: true);
    api.getProducts()
        .then(function(data) 
            actions.refreshProductFromData(response.data.products);
        );
        .catch(function(err) 
            this.setState(error: err);
        )
        .then(function() 
            this.setState(inProgress: false);
        );

不确定这是否是正确/最佳的解决方案。

【讨论】:

【参考方案2】:

我找到了你的帖子,因为我有同样的问题。我想我会像这样构建我的结构,保持一切解耦并通过行动进行交流。我喜欢保持组件和存储对 API 的无知。

产品操作知道如何与 API 交互以完成请求的操作。 Product Store 侦听 Completed 操作以更新其内部状态。 Lo​​adingAction 管理微调器状态,并在启动 API 调用时要求显示/隐藏微调器。 我有一个 Spinner 组件,它侦听 LoadingActions 并更新其状态以显示/隐藏微调器。

组件:

actions.refresh();

(产品)操作:

onRefresh: function () 
    LoadingActions.showSpinner();
    api.loadProducts().then(this.completed, this.failed).finally(LoadingActions.hideSpinner);

加载动作:

onShowSpinner: function ()  ... 
onHideSpinner: function ()  ... 

商店:

onRefreshCompleted: function (data) 
    this.products = data;
    this.trigger();

【讨论】:

以上是关于如何保留本地组件数据,例如微调器/错误,在 Flux 商店之外?的主要内容,如果未能解决你的问题,请参考以下文章

如何从微调器中检索数据并进行处理?

在组件中检索到响应后,加载微调器未隐藏

如何始终在移动设备和 iPad 上显示数字输入微调器

带有日期选择器的 Android 微调器,例如 Google 日历应用

在等待在 ReactJS 渲染中获取数据时显示加载微调器

显示异步 Vue 2 组件的加载微调器