Package Exports
- redux-api-middleware
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (redux-api-middleware) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
redux-api-middleware
Redux middleware for calling an API.
This middleware receives Redux Standard API-calling Actions and dispatches Flux Standard Actions as explained below.
Flux Standard Actions (FSA)
Recall the definition of a Flux Standard Action.
An action MUST
- be a plain JavaScript object,
- have a
typeproperty.An action MAY
- have an
errorproperty,- have a
payloadproperty,- have a
metaproperty.An action MUST NOT
- include properties other than
type,payload,errorandmeta.
typeThe
typeof an action identifies to the consumer the nature of the action that has occurred. Two actions with the sametypeMUST be strictly equivalent (using===). By convention,typeis usually a string constant or aSymbol.
payloadThe optional
payloadproperty MAY be any type of value. It represents the payload of the action. Any information about the action that is not thetypeor status of the action should be part of thepayloadfield.By convention, if
erroris true, thepayloadSHOULD be an error object. This is akin to rejecting a promise with an error object.
errorThe optional
errorproperty MAY be set totrueif the action represents an error.An action whose
erroris true is analogous to a rejected Promise. By convention, thepayloadSHOULD be an error object.If
errorhas any other value besidestrue, includingundefinedandnull, the action MUST NOT be interpreted as an error.
metaThe optional
metaproperty MAY be any type of value. It is intended for any extra information that is not part of the payload.
A Redux Standard API-calling Action conforms to a schema that comes close to being a superset of that of an FSA.
Redux Standard API-calling Actions (RSAA)
A Redux Standard API-calling Action MUST
- be a plain JavaScript object,
- have a
[CALL_API]property, whereCALL_APIis aSymboldefined in, and exported byredux-api-middleware.
A Redux Standard API-calling Action MAY
- have a
payloadproperty, - have a
metaproperty.
A Redux Standard API-calling Action MUST NOT
- include properties other than
[CALL-API],payload, andmeta.
[CALL_API]
The [CALL_API] property MUST
- be a plain JavaScript Object,
- have an
endpointproperty, - have a
methodproperty, - have a
typesproperty.
The [CALL_API] property MAY
- have a
bodyproperty, - have a
headersproperty, - have a
schemaproperty, - have a
bailoutproperty.
The [CALL_API] property MUST NOT
- include properties other than
endpoint,method,types,body,headers,schemaandbailout.
[CALL_API].endpoint
The [CALL_API].endpoint property must be a string or a function. In the second case, the function SHOULD return a string. It represents the URL endpoint for the API request.
[CALL_API].method
The [CALL_API].method property MUST be one of the strings GET, POST, PUT or DELETE (in any mixture of lowercase and uppercase letters). It represents the HTTP method for the API request.
[CALL_API].types
The [CALL_API].types property MUST be an array of length 3, representing the REQUEST, SUCCESS and FAILURE states of the API call, in that order. By convention, each of the types is usually a string constant or a Symbol.
[CALL_API].body
The optional [CALL_API].body property MUST be a plain JavaScript object. It represents the body of the API request.
[CALL_API].headers
The optional [CALL_API].headers property MUST be a plain JavaScript object. It represents the headers of the API request.
[CALL_API].schema
The optional [CALL_API].schema property MUST be a normalizr schema. It specifies with which normalizr schema we should process the API response
[CALL_API].bailout
The optional [CALL_API].bailout property MUST be a boolean or a function. When it returns a falsy value, the API request will not be made, and no FSA action will be dispatched to the next middleware.
payload
The optional payload property MAY be any type of value.
meta
The optional meta property MAY be any type of value. It is intended for any extra information that is not part of the payload or the [CALL_API] data.
What this middleware does
This middleware expects an RSAA and dispatches FSAs in the following way.
- An FSA with the
REQUESTtype is dispatched to the next middleware as soon as the RSAA comes in; thepayloadandmetaproperties of this FSA are those of the original RSAA. - If the request is successful, an FSA with the
SUCCESStype is dispatched to the next middleware; thepayloadproperty of this FSA is a merge of the original RSAA'spayloadproperty and the JSON response from the server; themetaproperty of this FSA is that of the original RSAA. - If the request is unsuccessful, an FSA with the
FAILUREtype is dispatched to the next middleware; thepayloadproperty of this FSA is set to the error object of the request; themetaproperty of this FSA is the same as that of the original RSAA; theerrorproperty of this FSA is set totrue.
If the incoming action does not contain a [CALL_API] key, it is passed to the next middleware without any modifications.
Example
actionCreators.js
import { CALL_API } from 'redux_api';
import { Schema } from 'normalizr';
const userSchema = new Schema({...});
export function fetchUser(userId, schema = userSchema) {
return {
[CALL_API]: {
types: ['FETCH_USER.REQUEST', 'FETCH_USER.SUCCESS', 'FETCH_USER.FAILURE'],
endpoint: `/users/${userId}`,
method: 'GET',
headers: { credentials: 'same-origin'},
schema
},
payload: { somePayload },
meta: { someMeta }
};
}The headers: { credentials: 'same-origin'} property sends the authentication credentials stored in cookies by an express server using passport (other options might work too).
configureStore.js
import { createStore, applyMiddleware, combineReducers } from 'redux';
import { apiMiddleware } from 'redux-api-middleware';
import reducers from './reducers';
const reducer = combineReducers(reducers);
const createStoreWithMiddleware = applyMiddleware(apiMiddleware)(createStore);
export default function configureStore(initialState) {
return createStoreWithMiddleware(reducer, initialState);
}app.js
const store = configureStore(initialState);Resulting actions
{
type: 'FETCH_USER.REQUEST',
payload: { somePayload },
meta: { someMeta }
}{
type: 'FETCH_USER.SUCCESS',
payload: { ...somePayload, response },
meta: { someMeta }
}{
type: 'FETCH_USER.FAILURE',
payload: error,
meta: { someMeta }
error: true
}Utilities
Apart from the middleware above, redux-api-middleware exposes the following utility function.
isRSAA(action)
Returns true if action is RSAA-compliant.
Installation
npm install redux-api-middlewareTests
npm testLicense
MIT
Acknowledgements
The code in this module is heavily based upon that in the real-world example in the redux repository, which I believe is due to Dan Abramov. Please correct me if I am wrong.