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
type
property.An action MAY
- have an
error
property,- have a
payload
property,- have a
meta
property.An action MUST NOT
- include properties other than
type
,payload
,error
andmeta
.
type
The
type
of an action identifies to the consumer the nature of the action that has occurred. Two actions with the sametype
MUST be strictly equivalent (using===
). By convention,type
is usually a string constant or aSymbol
.
payload
The optional
payload
property MAY be any type of value. It represents the payload of the action. Any information about the action that is not thetype
or status of the action should be part of thepayload
field.By convention, if
error
is true, thepayload
SHOULD be an error object. This is akin to rejecting a promise with an error object.
error
The optional
error
property MAY be set totrue
if the action represents an error.An action whose
error
is true is analogous to a rejected Promise. By convention, thepayload
SHOULD be an error object.If
error
has any other value besidestrue
, includingundefined
andnull
, the action MUST NOT be interpreted as an error.
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.
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_API
is aSymbol
defined in, and exported byredux-api-middleware
.
A Redux Standard API-calling Action MAY
- have a
payload
property, - have a
meta
property.
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
endpoint
property which is a string (representing the URL endppoint for the API request) or a function returning such string, - have a
method
property which is one of the stringsGET
,POST
,PUT
orDELETE
(representing the HTTP method for the API request), - have a
types
property which is an array of length 3, representing theREQUEST
,SUCCESS
andFAILURE
states of the API call, in that order (by convention, each of thetypes
is usually a string constant or aSymbol
).
The [CALL_API]
property MAY
- have a
body
property which is a plain JavaScript Object (representing the body of the API request), - have a
headers
property which is a plain JavaScript Object (representing the headers of the API request), - have a
schema
property which is anormalizr
schema (expressing with whichnormalizr
schema we should process the API response), - have a
bailout
property which is a function (deciding whether we should actually make the request or not).
The [CALL_API]
property MUST NOT
- include properties other than
endpoint
,method
,types
,body
,headers
,schema
andbailout
.
payload
The optional payload
property MAY be any type of value. It represents the payload of the action.
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
REQUEST
type is dispatched to the next middleware as soon as the RSAA comes in; thepayload
andmeta
properties of this FSA are those of the original RSAA. - If the request is successful, an FSA with the
SUCCESS
type is dispatched to the next middleware; thepayload
property of this FSA is a merge of the original RSAA'spayload
property and the JSON response from the server; themeta
property of this FSA is that of the original RSAA. - If the request is unsuccessful, an FSA with the
FAILURE
type is dispatched to the next middleware; thepayload
property of this FSA is set to the error message of the request (or the stringSomething bad happened
if the latter is empty); themeta
property of this FSA is the same as that of the original RSAA; theerror
property 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.message,
meta: { someMeta }
error: true
}
Utilities
Apart from the middleware above, redux-api-middleware
exposes the following utility function.
isRSAA(action)
Return true
if action
is RSAA-compliant.
Installation
npm install redux-api-middleware
Tests
TODO
License
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.