Reputation: 5319
As far as my understanding goes, it's an anti-pattern to dispatch actions from within a store update handler. Correct?
How can I handle the following workflow then?
SELECTEDCOMPANY_UPDATE
actioncompanyDataService.fetchOrders(companyName)
.FETCHINGDATA_UPDATE
which updates the fetchingData
section in my app state store to which all interested views can react by showing/hiding the load maskWhere do I actually dispatch the FETCHINGDATA_UPDATE
action? If I directly do this from within companyDataService.fetchOrders(companyName)
it would be called from within a store update handler (see OrdersView.onStoreUpdate
in exemplary code below)...
To clarify my last sentence I'm adding some exemplary code which shows how my implementation would have looked like:
ActionCreator.js
// ...
export function setSelectedCompany(company) {
return { type: SELECTEDCOMPANY_UPDATE, company: company };
}
export function setFetchingData(isFetching) {
return { type: FETCHINGDATA_UPDATE, isFetching: isFetching };
}
// ...
CompanyDataService.js
// ...
export fetchOrders(companyName) {
this.stateStore.dispatch(actionCreator.setFetchingData(true));
fetchData(companyName)
.then((data) => {
this.stateStore.dispatch(actionCreator.setFetchingData(false));
// Apply the data...
})
.catch((err) => {
this.stateStore.dispatch(actionCreator.setFetchingData(false));
this.stateStore.dispatch(actionCreator.setFetchError(err));
})
}
// ...
CompanySwitcher.js
// ...
onCompanyClicked(company) {
this.stateStore.dispatch(actionCreator.setSelectedCompany(company));
}
// ...
OrdersView.js
// ...
constructor() {
this._curCompany = '';
this.stateStore.subscribe(this.onStoreUpdate);
}
// ...
onStoreUpdate() {
const stateCompany = this.stateStore.getState().company;
if (this._curCompany !== stateCompany) {
// We're inside a store update handler and `fetchOrders` dispatches another state change which is considered bad...
companyDataService.fetchOrders(stateCompany);
this._curCompany = stateComapny;
}
}
// ...
Upvotes: 0
Views: 32
Reputation: 526
I agree with Davin, in the action creator is the place to do this, something like:
export function fetchOrders (company) {
return (dispatch) => {
dispatch ({ type: FETCHINGDATA_UPDATE });
return fetchOrderFunction ().then(
(result) => dispatch ({ type: FETCHING_COMPLETED, result }),
(error) => dispatch ({ type: FETCHING_FAILED, error })
);
};
}
Then in the reducer FETCHINGDATA_UPDATE can set your loading indicator to true and you can set it back to false I both SUCCESS and FAILED
Upvotes: 1