Note: I am using Reflux as my Flux library, so the samples will use its syntax. The question applies to Flux in general, however.
In my sample Flux application I have a productStore.js
file that holds the state of the products in the system and listens to various product management actions, e.g REMOVE_PRODUCT
, ADD_PRODUCT
.
Here is a sample data in the store:
{
products: [
{
productName: "A"
},
{
productName: "B"
}
]
}
Now I would like to add a REFRESH_PRODUCTS
action to a component.
The invocation looks like that:
component.jsx
onRefresh(e) {
actions.refreshProducts();
}
Since refreshing the products is an async operation, I would like to show the spinner while it goes on and show an error if it fails. The obvious, Flux way, would be to add the loading state and the resulting error, if such 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 store of the data becomes dirty with various flags:
{
inProgress: false,
error: null,
products: [
{
productName: "A"
},
{
productName: "B"
}
]
}
This kind of state would be perfectly fine for me if multiple components would need to see the progress of products loading, or refresh failing, but in case, no other components needs that kind of information. So it feels I am putting private data to global state without a good reason.
I would like to be able to do something like that:
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 code of store clean. However, I have no obvious way to do that - Actions, by design, create a separation that don't allow to return data from actions.
What's the proper way to do it? How can I do private spinners/errors/etc while keeping the related data out of global state?
Here is one solution I thought of while writing this question:
refreshProductFromData
Like so:
component.jsx
Not sure if it is the right/best solution or not however.