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
dispatchof one of theapiRequestactions
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