How to save data from local components eg. spinners / bugs, outside of Flux stores?

Note. I am using Reflux as my Flux library, so the samples will use their syntax. However, the question applies to Flux in general.

In my sample Flux application, there is a file productStore.js

that contains the state of the products on the system and listens for various product control actions such REMOVE_PRODUCT

as ADD_PRODUCT

.

Here's an example of data in the store:

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

      

Now I would like to add an action REFRESH_PRODUCTS

to the component.

The call looks like this:

component.jsx

onRefresh(e) {
    actions.refreshProducts();
}

      

Since updating products is an async operation, I would like to show the jiggle while it is running and showing an error if it is not working. The obvious Flux way would be to add the loading state and the resulting error, if it happens, to the store, like so:

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);
        });
}

      

And now the datastore is getting messy with various flags:

{
    inProgress: false,
    error: null,

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

      

Such a state would be fine for me if several components were to see the progress of product downloads or an update failure, but in case no other components need such information. So I feel like I am putting private data in the global state for no good reason.

I would like to do something like this:

component.jsx - BAD CODE

onRefresh(e) {

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

      

Then I could keep the store code clean. However, I have no obvious way to do this. Actions, by design, create separation that prevents data from being returned from actions.

What's the correct way to do this? How can I do private spinner / errors / etc while keeping related data from global state?

+3


source to share


2 answers


Here is one of the solutions I was thinking about while writing this question:

  • Create a new store action that allows you to update product data by argument, for example: refreshProductFromData

  • Call the API directly from the component
  • Manipulate spinner / error handling in a component
  • Pass the data received from the API to the store using a new action

Same:



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});
        });
}

      

Not sure if this is the right / best solution or not.

+1


source


I found your post because I had the same question. I think I'm going to structure mine like this, keeping everything unbound and communicating through actions. I like to maintain the component and store the API information.

  • Product Actions know how to interact with the API to perform the requested action.
  • The grocery store listens for the Completed activity to update its internal state.
  • The LoadingActions system manages the counter state and asks to show / hide the counter when API calls are initiated.
  • I have a Spinner component that listens to LoadActions and updates its state to show / hide the spinner.

component:

actions.refresh();

      

(Product) Actions:



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

      

Loading actions:

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

      

Store:

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

      

0


source







All Articles