Skip to content

Instantly share code, notes, and snippets.

@codfish
Last active April 20, 2020 20:40
Show Gist options
  • Save codfish/b96dd88d051e2c7d651746ce67b09dbf to your computer and use it in GitHub Desktop.
Save codfish/b96dd88d051e2c7d651746ce67b09dbf to your computer and use it in GitHub Desktop.
Dynamic RSAA (redux-api-middleware) cache middleware. Must come before rssa in middleware order.
import { RSAA } from 'redux-api-middleware';
import get from 'lodash/get';
/**
* Intercept redux api middleware actions and bailout of api resource requests
* if the resource is already in the store.
*
* NOTE: State always gets updated on non-GET requests, essentially updating our "cache"
*
* Examples of resource routes that we want to cache:
* - /collection
* - /collection/<primary-key>
*
* Note: <primary-key> has to be something with non-alpha characters. guids, eth address, integer,
* mongoid's would all work, but it's not a perfect science. Adjust the regex accordingly.
*
* @see {@link https://github.com/agraboso/redux-api-middleware#bailing-out}
*/
export default function cacheMiddleware() {
return next => action => {
// if action is an api GET request for a resource we already have, prevent the request
if (action[RSAA] && action[RSAA].method === 'GET' && !action[RSAA].bailout) {
const url = new URL(action[RSAA].endpoint);
const pathParts = url.pathname.split('/').slice(1);
// if it's not a resource route then just keep moving
// NOTE: For "resource" routes, the last item in the url path should be an address
// and the second to last item should be the resource name/type.
let resource = pathParts[pathParts.length - 2];
let primaryKey = pathParts[pathParts.length - 1];
if (!resource || primaryKey.match(/^[a-zA-Z-_]+$/)) {
resource = pathParts[pathParts.length - 1];
primaryKey = null;
}
// Set the bailout property of the RSAA action object. Should be a function that returns
// a boolean. If it's true the request will NOT happen. Function takes redux state as a param.
// @see {@link https://github.com/agraboso/redux-api-middleware#bailing-out}
// eslint-disable-next-line no-param-reassign
action[RSAA].bailout = state => get(state, `entities.${resource}${primaryKey && `.${primaryKey}`}`, false) !== false;
}
return next(action);
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment