Skip to content

Commit c164f4c

Browse files
author
Artur Charaev
committed
add readme
1 parent 0ca7dec commit c164f4c

File tree

1 file changed

+278
-2
lines changed

1 file changed

+278
-2
lines changed

README.md

Lines changed: 278 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,279 @@
1-
redux-simpleapi-middleware
1+
redux-callapi-middleware
22
====================
3-
Middleware to call API in redux way.
3+
Redux CallAPI Middleware to make API calls in generic and declarative way.
4+
5+
## Contents
6+
7+
1. [Example](#example)
8+
2. [Usage and Docs](#usage-and-docs)
9+
1. [Installation](#installation)
10+
2. [Create middleware](#create-middleware)
11+
3. [Action creator](#action-creator)
12+
4. [Lifecycle](#lifecycle)
13+
5. [Dispatched FSAs](#dispatched-fsas)
14+
3. [FAQ](faq)
15+
4. [Acknowledgements](acknowledgements)
16+
5. [License](License)
17+
18+
## Example
19+
This is the simplest form, nothing wrong here, but take a look at [create middleware](#create-middleware) and [action creator](#action-creator) sections if you need customization, its quite flexible.
20+
21+
```js
22+
// actions file
23+
import { CALL_API } from `redux-callapi-middleware`;
24+
25+
export const callApi = () => ({
26+
[CALL_API]: {
27+
types: ['REQUEST', 'SUCCESS', 'FAILURE'],
28+
endpoint: 'http://yourdomain.com/api/posts',
29+
options: {
30+
method: 'GET'
31+
}
32+
}
33+
});
34+
35+
// somewhere
36+
import { callApi } from 'actions';
37+
dispatch(callApi());
38+
```
39+
40+
This will dispatch *request* FSA before request:
41+
42+
```js
43+
{ type: 'REQUEST' }
44+
```
45+
46+
If everything is fine it will dispatch *success* FSA on request response:
47+
48+
```js
49+
{
50+
type: 'SUCCESS',
51+
payload: payload
52+
}
53+
```
54+
55+
Otherwise it will dispatch *failure* FSA:
56+
57+
```js
58+
{
59+
type: 'FAILURE',
60+
payload: error,
61+
error: true
62+
}
63+
```
64+
65+
## Usage and Docs
66+
67+
### Installation
68+
69+
1. Install `redux-callapi-middleware` through [npm](https://www.npmjs.com/package/redux-callapi-middleware):
70+
71+
```js
72+
$ npm install redux-callapi-middleware --save
73+
```
74+
2. Add middleware with redux `applyMiddleware()`:
75+
76+
```js
77+
import { createStore, applyMiddleware } from 'redux';
78+
import apiMiddleware from 'redux-callapi-middleware';
79+
import reducers from './reducers';
80+
81+
const store = createStore(
82+
reducers,
83+
applyMiddleware(apiMiddleware)
84+
);
85+
```
86+
87+
### Create middleware
88+
89+
Middleware exposes `createMiddleware` function which accepts object with `status` and `parse` functions.
90+
So you can customize status and parse functions on your own.
91+
92+
```js
93+
import { createMiddleware } from 'redux-callapi-middleware';
94+
95+
const status = (response) => response;
96+
const parse = (response) => response;
97+
const apiMiddleware = createMiddleware({ status, response });
98+
```
99+
100+
#### `checkStatus`
101+
102+
Small util to check if `response.ok` (status in the range 200-299) used as default status check. If not it throws error with response attached to it in `error.response`. Failure handler will receive this error.
103+
104+
#### `parseResponse`
105+
106+
Small util to check to parse typical response like json or text and used as default parse function. If unknow type it returns raw response (for instance images).
107+
108+
### Action creator
109+
110+
Action creator should return an object with `[CALL_API]` property with `endpoint`, `options` and `types` fields. See [example](#example).
111+
112+
#### `[CALL_API].endpoint`
113+
114+
An API endpoint to call. String or function which receives state and returns string.
115+
116+
#### `[CALL_API].options`
117+
118+
Request options object. Object or function which receives state and returns object.
119+
It uses [`isomorphic-fetch`](https://github.com/matthew-andrews/isomorphic-fetch) under the hood, so any valid options for [fetch](https://fetch.spec.whatwg.org), like `body`, `credentials`, `headers` and etc.
120+
121+
#### `[CALL_API].types`
122+
123+
Array of actions to dispatch as middleware output. It might be strings or symbols or FSA's or functions which should return FSA's or mix of them.
124+
So its fine to have following structure in `[CALL_API].types`:
125+
126+
```js
127+
[
128+
(action, state) => ({
129+
type: 'REQUEST',
130+
payload: { isFetching: true }
131+
}),
132+
{ type: 'SUCCESS' },
133+
'FAILURE'
134+
]
135+
```
136+
137+
### How it works
138+
139+
1. Checks if action has `[CALL_API]`. If no it stops and dispatches action to next middleware.
140+
2. Builds request endpoint and options. There might be error handling in future.
141+
3. Dispatches to next middleware *request* FSA from first item of `[CALL_API].types`.
142+
4. Performs API call by request params.
143+
5. Checks response status with `checkStatus` function (see [create middleware](#create-middleware)). If succeed it will try to parse response with `parseResponse` function (see [create middleware](#create-middleware)) and will dispatch *success* FSA from second item of `[CALL_API].types`. Otherwise, it will dispatch *failure* FSA from third item of `[CALL_API].types`.
144+
145+
### Dispatched FSAs
146+
147+
The `[CALL_API].types` array can hold 4 kind of actions types:
148+
* `strings` - will be converted to FSA `object`.
149+
* `symbols` - same as strings.
150+
* `object` - it should be valid FSA `object`.
151+
```js
152+
{
153+
type: 'REQUEST',
154+
payload: {
155+
page: 5
156+
}
157+
}
158+
```
159+
* `function` - most flexible way it will receive 3 arguments: `[CALL_API]` object, state and payload. But it should return valid FSA `object`.
160+
```js
161+
(apiAction, state, payload) => ({
162+
type: 'SUCCESS',
163+
payload
164+
})
165+
```
166+
167+
#### Request FSA
168+
169+
Not receives payload as FSA property or function argument from middleware. (There is no payload at this moment)
170+
171+
#### Success FSA
172+
173+
Receives response as payload, it will be converted to json or text by middleware.
174+
175+
#### Failure FSA
176+
177+
Receives error as payload, response attached to `error.response` property. FSA also have error flag set to true.
178+
179+
## FAQ
180+
181+
1. Usage with thunk (dont forget to put api middleware *after* thunk in middleware chain):
182+
183+
```js
184+
import { CALL_API } from `redux-callapi-middleware`;
185+
186+
const callApi = () => (
187+
(dispatch, getState) =>
188+
// do anything you need here
189+
190+
return dispatch({
191+
[CALL_API]: {
192+
types: ['REQUEST', 'SUCCESS', 'FAILURE'],
193+
endpoint: 'http://yourdomain.com/api/posts',
194+
options: {
195+
method: 'GET'
196+
}
197+
}
198+
})
199+
)
200+
```
201+
202+
2. Need a meta property in FSA?
203+
204+
```js
205+
{
206+
[CALL_API]: {
207+
types: [{
208+
type: 'REQUEST',
209+
meta: 'anything'
210+
},
211+
(apiAction, state, payload) => (
212+
{
213+
type: 'SUCCESS',
214+
payload,
215+
meta: payload.meta
216+
}
217+
), {
218+
type: 'FAILURE',
219+
meta: 'anything'
220+
}],
221+
endpoint: 'http://yourdomain.com/api/posts',
222+
options: {
223+
method: 'GET'
224+
}
225+
}
226+
}
227+
```
228+
229+
3. Need a payload function? Use `function` action type in `[CALL_API].types` and build own FSA.
230+
```js
231+
{
232+
[CALL_API]: {
233+
types: [
234+
'REQUEST',
235+
'SUCCESS',
236+
// lets pass failure type as function
237+
(apiAction, state, error) => {
238+
// do anything you need but return FSA object
239+
const payload = formatErrorPayload(error)
240+
return {
241+
type: 'FAILURE',
242+
meta: 'anything',
243+
payload
244+
};
245+
}],
246+
endpoint: 'http://yourdomain.com/api/posts',
247+
options: {
248+
method: 'GET'
249+
}
250+
}
251+
}
252+
```
253+
254+
4. Need a `promise` as output action?
255+
256+
Not supported, but might work with [redux-promise](https://github.com/acdlite/redux-promise).
257+
258+
5. Difference with [redux-api-middleware](https://github.com/agraboso/redux-api-middleware)?
259+
1. It dispatches errors only with *error* type
260+
2. It not dispatches "programmatic" errors, like errors on endpoint generation.
261+
3. It gives more control with functions as actions types
262+
4. Not supports promises, but take look to [redux-promise](https://github.com/acdlite/redux-promise).
263+
264+
6. Want to have base URL?
265+
266+
Write a wrapper around your callApi action creator.
267+
268+
7. Want to check custom headers or custom parse response?
269+
270+
See [create middleware](#create-middleware)
271+
272+
## Acknowledgements
273+
274+
Originally inspired and extracted from [Dan Abramov](https://github.com/gaearon) the [real-world](https://github.com/rackt/redux/blob/master/examples/real-world/middleware/api.js) sample in the [redux](https://github.com/rackt/redux) repository. Thanks to all developers and contributors.
275+
276+
## License
277+
278+
The MIT License (MIT)
279+
Copyright (c) 2017 Artur Charaev

0 commit comments

Comments
 (0)