Comment on page

createResource

Creates a resource and associated actions and selectors to interact with it

Arguments

  1. 1.
    (resourceName): (string) The name under which the resource will be stored in the state
  2. 2.
    (options): (object) An object containing additional, optional options for the resource:
    A. (cacheLifetime): (number, default: 0) The duration (in seconds) for which the resource will be considered valid (from 0 - no cache - to Infinity - cached permanently)
    B. (denormalizer): ((resourceIds, resources) : array<resources>, default null) A function useful to denormalize nested objects which have been normalized by actionName.normalizer (e.g. via normalizr)
  3. 3.
    (actions): (map<actionName:config>) An object of configs with the following attributes:
const resource = {
// Mandatory
method: 'GET|POST|PATCH|PUT|DELETE',
url: string || func,
// Optional
beforeHook: func,
normalizer: func,
metadataNormalizer: func,
afterHook: func,
// Also optional. Override the built-in network helpers
// and the ones you may have provided using initializeNetworkHelpers
networkHelpers: {
getToken: func,
requestGET: func,
requestPATCH: func,
requestPUT: func,
requestPOST: func,
requestDELETE: func,
handleStatusCode: func,
handleError: func,
},
},
...
};
Extensive documentation on actions configuration can be found here.

Returns

(Object): An object containing actions and selectors.
const resource = {
actions: object,
selectors: object,
};

Example

This example demonstrates how to use createResource to create a sample resource, and then to export the reducers, actions and selectors.
import { createResource } from '@brigad/redux-rest-easy';
const users = createResource('users', { cacheLifetime: 30 })({
retrieve: {
method: 'GET',
url: 'https://my-api.com/users',
beforeHook: () => console.log('About to retrieve users... Hang on!'),
},
retrieveById: {
method: 'GET',
url: 'https://my-api.com/users/::userId',
},
create: {
method: 'POST',
url: 'https://my-api.com/users',
afterHook: () => console.log('User created!'),
normalizer: ({ user }) => ({
entities: { users: { [user.id]: user } },
result: user.id,
}),
},
edit: {
method: 'PATCH',
url: 'https://my-api.com/users/::userId',
},
});
const {
actions: {
resource: {
invalidate: invalidateUsers,
invalidateId: invalidateUser,
reset: resetUsers,
},
retrieve: { perform: retrieveUsers, invalidate: invalidateRetrieveUsers },
retrieveById: { perform: retrieveUser, invalidate: invalidateRetrieveUser },
create: { perform: createUser },
edit: { perform: editUser },
},
selectors: {
resource: { getResource: getAllUsers, getResourceById: getUserById },
retrieve: {
resource: {
couldPerform: couldRetrieveAnyUsers,
isPerforming: isRetrievingAnyUsers,
hasSucceeded: hasRetrievedAnyUsers,
hasFailed: hasFailedAnyUsers,
isValid: areAllUsersValid,
couldPerformOnId: couldRetrieveUser,
isPerformingOnId: isRetrievingUser,
hasSucceededOnId: hasRetrievedUser,
hasFailedOnId: hasFailedUser,
isValidId: isUserValid,
},
request: {
getResource: getUsers,
getMetadata: getUsersMetadata,
couldPerform: couldRetrieveUsers,
isPerforming: isRetrievingUsers,
hasSucceeded: hasRetrievedUsers,
hasFailed: hasFailedUsers,
isValid: areUsersValid,
},
},
},
} = users;
export {
retrieveUsers,
retrieveUser,
createUser,
editUser,
invalidateUsers,
invalidateUser,
invalidateRetrieveUsers,
invalidateRetrieveUser,
resetUsers,
getAllUsers,
getUserById,
couldRetrieveAnyUsers,
isRetrievingAnyUsers,
hasRetrievedAnyUsers,
hasFailedAnyUsers,
areAllUsersValid,
couldRetrieveUser,
isRetrievingUser,
hasRetrievedUser,
hasFailedUser,
isUserValid,
getUsers,
getUsersMetadata,
couldRetrieveUsers,
isRetrievingUsers,
hasRetrievedUsers,
hasFailedUsers,
areUsersValid,
};

Tips

  • The above example is very exhaustive, but you can export only what you really need
  • Naming is a matter of personal preference, use what works for you
  • You can alternately just export users, and spare yourself the trouble of mapping the names. Then just use the selectors like so: users.selectors.resource.getResource(). Again, use what works for you