createResource
Creates a resource and associated actions and selectors to interact with it
Arguments
(resourceName): (
string) The name under which the resource will be stored in the state(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 (from0- no cache - toInfinity- cached permanently)B. (denormalizer): (
(resourceIds, resources) : array<resources>, default null) A function useful to denormalize nested objects which have been normalized byactionName.normalizer(e.g. via normalizr)(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
Last updated