关于reactjs:如何保留本地组件数据在Flux商店外的微调器/错误?

How to keep local component data , e.g. spinners/errors, outside of Flux stores?

注意:我将Reflux用作我的Flux库,因此示例将使用其语法。但是,该问题通常适用于助焊剂。

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

以下是商店中的示例数据:

1
2
3
4
5
6
7
8
9
10
{
    products: [
        {
            productName:"A"
        },
        {
            productName:"B"
        }
    ]
}

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

调用看起来像这样:

component.jsx

1
2
3
onRefresh(e) {
    actions.refreshProducts();
}

由于刷新产品是异步操作,因此我想在微调器启动时显示它,如果失败则显示错误。明显的Flux方法是将加载状态和由此产生的错误(如果发生的话)添加到存储中,如下所示:

productStore.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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);
        });
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
{
    inProgress: false,
    error: null,

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

如果多个组件需要查看产品加载进度或刷新失败,但是对于其他组件,则不需要这种信息。因此,感觉到我没有充分理由就将私有数据置于全球状态。

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

component.jsx-错误代码

1
2
3
4
5
6
7
8
9
10
11
onRefresh(e) {

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

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

正确的做法是什么?如何在使相关数据不进入全局状态的同时进行私有微调/错误/等操作?


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

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

例如:

component.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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});
        });
}

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


我找到了您的信息,因为我有同样的问题。我想我将像这样构造我的矿井,保持一切脱钩,并通过行动进行交流。我喜欢保留有关该组件的信息,并存储有关该API的信息。

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

组件:

1
actions.refresh();

(产品)操作:

1
2
3
4
onRefresh: function () {
    LoadingActions.showSpinner();
    api.loadProducts().then(this.completed, this.failed).finally(LoadingActions.hideSpinner);
}

加载操作:

1
2
onShowSpinner: function () { ... }
onHideSpinner: function () { ... }

商店:

1
2
3
4
onRefreshCompleted: function (data) {
    this.products = data;
    this.trigger();
}