Skip to content

Instantly share code, notes, and snippets.

@jtangelder
Last active March 20, 2016 17:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jtangelder/870dcc6f55717959d864 to your computer and use it in GitHub Desktop.
Save jtangelder/870dcc6f55717959d864 to your computer and use it in GitHub Desktop.
Redux resources, untested
/*
Create (cacheable) resources, and endpoints that require some state that you want to hide from the
arguments, like a JWT for authenticating remote calls.
Returns a function that will be accepted by redux-thunk.
*/
/**
* create a redux-resource function
* @param {Function} remote(args, getState)
* @param {Function} local(args, getState)
* @returns {Function} thunk(dispatch, getState)
*/
export function createResource({ remote, local }) {
return (args, handler) => {
return (dispatch, getState) => {
const callHandler = resource => handler(resource, dispatch, getState);
const callFetch = fetcher => fetcher(args, getState);
const localResult = local ? callFetch(local) : undefined;
if (localResult === undefined) {
return callHandler(callFetch(remote));
}
return callHandler(Promise.resolve(localResult));
}
}
}
/**
* simple function to create a remote-only api endpoint
* @param {Function} remote
* @returns {Function} thunk(dispatch, getState)
*/
export function createRemoteResource(remote) {
return createResource({ remote });
}
/*
Usage for some simple endpoints
*/
const getProductById = createResource({
/**
* fetch remote data
* @param {Object} arguments
* @param {Function} getState
* @returns {Promise}
*/
remote ({ productId }, getState) {
return window.fetch(`/product/${productId}`, {
headers: {
Authorization: `bearer ${getState().jwt}`
}
});
},
/**
* get local state, result wil get wrapped in a Promise.resolve.
* if it returns undefined, the remote data will be fetched.
* @param {Object} arguments
* @param {Function} getState
* @returns {*}
*/
local ({ productId }, getState) {
return getState().products[productId];
}
});
const getUserById = createRemoteResource(({ userId }) => {
return window.fetch(`/user/${userId}`);
});
/*
implementation in a Redux action
*/
function fetchUser(userId) {
return getUserById({ userId }, (resource, dispatch) => {
dispatch({ type: 'FETCH_USER' });
return resource
.then(user => dispatch(fetchUserSuccess(user)))
.catch(error => dispatch(fetchUserFailed(error)))
});
}
function fetchUserSuccess(user) {
return {
type: 'FETCH_USER_SUCCESS',
payload: { user }
};
}
function fetchUserFailed(error) {
return {
type: 'FETCH_USER_FAILED',
payload: { error }
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment