suamikim
suamikim

Reputation: 5319

How to avoid action from within store update

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?

Where 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)...


Edit

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

Answers (1)

user2997982
user2997982

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

Related Questions