createResource

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

Arguments

  1. (resourceName): (string) The name under which the resource will be stored in the state

  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. (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