Skip to content

Work in Progress - Opinionated HOFs for auto-generating REST API consuming redux logic

License

Notifications You must be signed in to change notification settings

FredKSchott/redesert

 
 

Repository files navigation

Disclaimer: The APIs will change to be more consistent in v1.0.0. By then we also hope to have destructured the library so that it is decoupled from redux-thunk and reselect, so that developers that may want to swap out parts of the redux cycle (like using sagas instead of thunks) with other libraries may do so.

Redesert

Build Status

Redux, but the boiler plate DRY'ed up. Just define your resource. redesert is a set of higher order functions that automatically generate reducers, selectors, actions, and action creators mainly geared for handling REST API request cycles.

TL;DR The state slices output from the reducers are strictly opinionated but general. However, because of that we can auto-generate other portions of the data life cycle.

A state slice generally looks like this:

/*
[resource]: {
  [entitiesPath]: {
    [entity.id]: {
      ...otherProps // Developer defines these
      isFetching: boolean, // Pending status for a GET for a single entity
      isCreating: boolean, // Pending status for a POST for a single entity
      isUpdating: boolean, // Pending status for a PUT/PATCH for a single entity
      isRemoving: boolean, // Pending status for a DELETE for a single entity
    }
  },
  errors?: any
  isFetching: boolean // Only for the status of GET'ing a collection
}
*/

Table of Contents

Installation

npm install --save redesert reselect redux-thunk

or

yarn add redesert reselect redux-thunk

Basic Example

Following the "ducks" module pattern, this example puts all redux related logic into a single file.

import {
  apiThunk,
  makeResourceReducer,
  makeResourceSelectors,
  resourceApiActionTypesFactory,
} from 'redesert';

// Resources are usually a model from your backend
const resource = 'foo';
// Create action types that redesert functions understand and expect
const fooApiActionTypes = resourceApiActionTypesFactory(resource);

// Syntax for action creators that are already bound to dispatch in Containers
export const fetchFoos = () =>
  apiThunk({
    baseActionType: fooApiActionTypes.FETCH,
    networkRequest: () => fetch('/api/foos'), // Or whatever request library
    sucessNormalizer: someFn, // Normalize the response from the endpoint
    failureNormalizer: someFn, // Normalize an error from the endpoint
  });

// Dynamically generated base selectors, can compose more selectors from these.
export const {
  getFooEntities,
  getFooById,
  getFooErrors,
  getFooErrorsByid,
  getAreFooEntitiesFetching,
  getIsFooFetching,
  getIsFooUpdating,
  getIsFooRemoving,
} = makeResourceSelectors({ resource });

// Handles all basic CRUD action types, dispatched from apiThunk.
// Import and use in root reducer instantiation.
export const fooReducer = makeResourceReducer({ resource });
/*
Ouputs a state that looks like:

[resource]: {
  [entitiesPath]: {
    [entity.id]: entity
  },
  errors?: any
  isFetching: boolean // Only for the status of GET'ing a collection
}
*/

In action, inside example projects:

How does it work?

Creates action types that generated reducers automatically have cases for, and apiThunk automatically dispatches

Composed of three distinct pieces of logic:

  1. It follows the basic network request logic flow of:
    • *__START a network request. Signifies the request is in flight
    • *__SUCCESS response from the endpoint (success)
    • *__FAILURE response from the endpoint (error)
    • Relevant actions pertaining to the above are dispatched throughout that flow
  2. Normalization of response bodies for success and failed cases
    • This is how developers control the data shape of entities within the redux store
  3. API requesting call
    • Allows apiThunk to be completely agnostic of what a developer's choice of request library is, or its configurations (such as headers, content types, etc)

Creates a reducer that has cases for the life cycle suffixes dispatched from apiThunk.

  • The resource reducer will only parse action types of the passed in resource, or any action types defined in externalActionTypes
  • Each REST action has its own cases for the suffixes. This yields generic action types that look like: <API_ACTION>__resource__<SUFFIX>
  • The reducer outputs an expected strict state data structure layout

makeResourceSelectors

Creates reselect selectors that traverse the expected state and returns commonly accessed data. These selectors can also be used (through reselect) to compose more specific selectors for your application.

About

Work in Progress - Opinionated HOFs for auto-generating REST API consuming redux logic

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages

  • TypeScript 100.0%