Adding caching to API actions

In most cases, we want to setup our API actions such that we don't execute more api calls than neccessary.

apiGetEntity and apiGetCollection

There is a caching option build into apiGetEntity and apiGetCollection. Please look at the documentation for these helper actions.

Manual caching

Sometimes it is not possible to use the helper actions like apiGetEntity to get data from the API. In those cases we might use the lower-level actions such as apiGet(). In that case, it is often important to add some code that does manual caching. Consider the following example:

export const getUserInteractions = () => (dispatch, getState) => {
  const { interactions } = getState();

  if (interactions.loadedInitial) {
    return Promise.resolve();
  }

  return dispatch(
    createAction(GET_USER_INTERACTIONS)(dispatch(apiGet(
      REQUEST_USER_INTERACTIONS,
      GATEWAY_COMMUNITY_AUTH,
      '/aggregators/interactioninfo'
    )).then(({ data }) => Object.keys(data).forEach(interactionType => dispatch(addInteractions(
      interactionType,
      data[interactionType]
    )))))
  );
};

Generally, this caching follows the following pattern:

  • Convert the action into a thunk action ((dispatch, getState) => ...)
  • Check in Redux state if we already have the data we're looking for
  • If we have the data, return a Promise that resolves immediately
  • If we don't have the data, return the dispatch of one of the apiRequest actions

Preventing duplicate simultaneous API requests

The above instructions prevent us from doing an api request for data that we have already loaded in the past. But it doesn't protect against duplicate API requests when a request is still in progress. Currently we don't have a built-in solution for this. To work around this issue, we can use the dedupeAsyncThunk utility. If you dispatch a thunk action that is wrapped in dedupeAsyncThunk while another call is still pending, it will return the Promise for that call instead of re-executing the function. See the api docs for more info