1

I'm having trouble wrapping my head around how to handle api calls as a result of updates to data only the store should know how to perform (business logic). The basic flow is as follows:

AdComponent#_changeGeoTargeting calls the action creator UnpaidIntents#updateTargeting which dispatches an ActionTypes.UPDATE_TARGETS action which is handled like so:

AdStore.dispatchToken = Dispatcher.register(action => {
  switch(action.type) {
    case ActionTypes.UPDATE_TARGETS:
      // Business logic to update targeting from an action payload.
      // `payload` is an object, e.g. `{ geos: geos }`, `{ devices: devices }`,
      // etc.
      _unpaid.targeting = _calcTargeting(
        _unpaid.targeting, action.payload);

      // Ajax call to fetch inventory based on `Ad`s parameters
      WebAPIUtils.fetchInventoryPredictions(
        _unpaid.start, _unpaid.end, _unpaid.targeting)
        .then((resp) => {
          var key = _makeCacheKey(
            _unpaid.start, _unpaid.end, _unpaid.targeting);
          // Updates store's inventory cache
          _updateInventoryCache(key, resp);
        })
        .catch((error) => {
          // How can I handle this error?  If this request
          // was executed inside an action I could have my
          // `NotiticationsStore` listening for
          // `ActionTypes.INVENTORY_PREDICTIONS_ERROR`
          // and updating itself, but I can't dispatch here.
        });
      break;
    default:
      return true;
  }
  AdStore.emitChange();
  return true;
});

The problem being that this call can't dispatch other actions since it's in a store.

I could make the call in the action creator, but that requires it to know how to update the Ad. I was under the impression that action creators should be dumb "dispatcher helper methods", and something like this would violate those principles:

UnpaidIntents.updateTargeting = (ad, value) => {
  var targeting = _calcTargeting(ad.targeting, value);

  WebAPIUtils.fetchInventoryPredictions(ad.start, ad.end, targeting)
    .then((resp) => {
      Dispatcher.dispatch({
        type: ActionTypes.UPDATE_TARGETING,
        payload: {
          targeting: targeting,
          inventory: resp,
        },
      });
    })
    .catch((error) => {
      Dispatcher.dispatch({
        type: ActionTypes.INVENTORY_PREDICTIONS_ERROR,
        payload: error,
      });
    });
};

Would breaking out _calcTargeting into an AdUtils module and using that as my business logic layer be the way to do this? I'm afaid if I have business logic in utils and possibly also stores that things will get messy very quickly.

Can anyone give some guidance here?

Jeremy D
  • 4,787
  • 1
  • 31
  • 38
David Wick
  • 7,055
  • 2
  • 36
  • 38
  • May this could partly help: http://stackoverflow.com/questions/26632415/where-should-ajax-request-be-made-in-flux-app – Dustin Hoffner Apr 16 '15 at 19:18
  • There is a nice article on async requests that describes the principle off putting the Api calls into the action creator. You can find it over here: http://www.code-experience.com/async-requests-with-react-js-and-flux-revisited/ – Björn Boxstart Apr 16 '15 at 19:59
  • more discussion here: https://groups.google.com/forum/#!topic/reactjs/Iz2xYUapX8k – David Wick Apr 17 '15 at 01:58

0 Answers0