UNPKG

8.93 kBMarkdownView Raw
1# redux-axios-middleware
2
3Redux middleware for fetching data with axios HTTP client
4
5## Installation
6
7```bash
8npm i -S redux-axios-middleware
9```
10
11## How to use?
12
13### Use middleware
14
15By default you only need to import middleware from package and add it to redux middlewares and execute it with first argument being with axios instance. second optional argument are middleware options for customizing
16
17```js
18import {createStore, applyMiddleware} from 'redux';
19import axios from 'axios';
20import axiosMiddleware from 'redux-axios-middleware';
21
22const client = axios.create({ //all axios can be used, shown in axios documentation
23 baseURL:'http://localhost:8080/api',
24 responseType: 'json'
25});
26
27let store = createStore(
28 reducers, //custom reducers
29 applyMiddleware(
30 //all middlewares
31 ...
32 axiosMiddleware(client), //second parameter options can optionally contain onSuccess, onError, onComplete, successSuffix, errorSuffix
33 ...
34 )
35)
36```
37
38### Dispatch action
39
40Every action which have `payload.request` defined will be handled by middleware. There are two possible type definitions.
41
42- use `action.type` with string name
43- action with type will be dispatched on start, and then followed by type suffixed with underscore and
44- success suffix on success, or error suffix on error
45
46defaults: success suffix = "_SUCCESS" error suffix = "_FAIL"
47
48```javascript
49export function loadCategories() {
50 return {
51 type: 'LOAD',
52 payload: {
53 request:{
54 url:'/categories'
55 }
56 }
57 }
58}
59```
60
61- use `action.types` with array of types `[REQUEST,SUCCESS,FAILURE]`
62- `REQUEST` will be dispatched on start, then `SUCCESS` or `FAILURE` after request result
63
64```javascript
65export function loadCategories() {
66 return {
67 types: ['LOAD','AWESOME','OH_NO'],
68 payload: {
69 request:{
70 url:'/categories'
71 }
72 }
73 }
74}
75```
76
77Actions that are handled by this middleware return a promise. This gives you the ability to chain actions. A good example of this might be a form. In the form you might dispatch an actions to store the form values. The normal flow of the action into the reducers would not be altered but you can chain a then/catch onto the initial dispatch.
78
79```javascript
80this.props.saveForm(formData)
81 .then(() => {
82 // router the user away
83 this.context.router.push("/my/home/page")
84 })
85 .catch((response) => {
86 //handle form errors
87 })
88```
89
90Another example might be a set of actions that you want dispatched together.
91
92```javascript
93Promise.all([
94 dispatch(foo()),
95 dispatch(bar()),
96 dispatch(bam()),
97 dispatch(boom())
98
99]).then(() => {
100 dispatch(
101 loginSuccess(
102 token
103 )
104 )
105})
106```
107
108### Request complete
109
110After request complete, middleware will dispatch new action,
111
112#### on success
113
114```javascript
115{
116 type: 'AWESOME', //success type
117 payload: { ... } //axios response object with data status headers etc.
118 meta: {
119 previousAction: { ... } //action which triggered request
120 }
121}
122```
123
124#### on error
125
126Error action is same as success action with one difference, there's no key `payload`, but now there's `error`;
127
128```js
129{
130 type:'OH_NO',
131 error: { ... }, //axios error object with message, code, config and response fields
132 meta: {
133 previousAction: { ... } //action which triggered request
134 }
135}
136```
137
138#### if axios failed fatally, default error action with status `0` will be dispatched.
139
140```js
141{
142 type:'OH_NO',
143 error: {
144 status: 0,
145 ... //rest of axios error response object
146 },
147 meta: {
148 previousAction: { ... } //action which triggered request
149 }
150}
151```
152
153### Multiple clients
154
155If you are using more than one different APIs, you can define those clients and put them to middleware. All you have to change is import of middleware, which is passed to redux createStore function and defined those clients.
156
157```
158import { multiClientMiddleware } from 'redux-axios-middleware';
159createStore(
160 ...
161 multiClientMiddleware(
162 clients, // described below
163 options // optional, this will be used for all middleware if not overriden by upper options layer
164 )
165)
166```
167
168`clients` object should be map of
169
170```
171{
172 client: axiosInstance, // instance of axios client created by axios.create(...)
173 options: {} //optional key for passing specific client options
174}
175```
176
177For example:
178
179```
180{
181 default: {
182 client: axios.create({
183 baseURL:'http://localhost:8080/api',
184 responseType: 'json'
185 })
186 },
187 googleMaps: {
188 client: axios.create({
189 baseURL:'https://maps.googleapis.com/maps/api',
190 responseType: 'json'
191 })
192 }
193}
194```
195
196Now in every dispatched action you can define client used:
197
198```javascript
199export function loadCategories() {
200 return {
201 type: 'LOAD',
202 payload: {
203 client: 'default', //here you can define client used
204 request:{
205 url:'/categories'
206 }
207 }
208 }
209}
210```
211
212If you don't define client, default value will be used. You can change default client name in middleware options.
213
214### Middleware options
215
216Options can be changed on multiple levels. They are merged in following direction:
217
218```
219default middleware values < middleware config < client config < action config
220```
221
222All values except interceptors are overriden, interceptors are merged in same order. Some values are changeable only on certain level (can be seen in change level column).
223
224Legend: `M` - middleware config `C` - client config `A` - action config
225
226key | type | default value | change level | description
227---------------------------- | ------------------------------------ | --------------------------------------------------------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
228successSuffix | string | SUCCESS | `M` `C` `A` | default suffix added to success action, for example `{type:"READ"}` will be `{type:"READ_SUCCESS"}`
229errorSuffix | string | FAIL | `M` `C` `A` | same as above
230onSuccess | function | described above | `M` `C` `A` | function called if axios resolve with success
231onError | function | described above | `M` `C` `A` | function called if axios resolve with error
232onComplete | function | described above | `M` `C` `A` | function called after axios resolve
233returnRejectedPromiseOnError | bool | false | `M` `C` `A` | if `true`, axios onError handler will return `Promise.reject(newAction)` instead of `newAction`
234isAxiosRequest | function | function check if action contain `action.payload.request` | `M` | check if action is axios request, this is connected to `getRequestConfig`
235getRequestConfig | function | return content of `action.payload.request` | `M` `C` `A` | if `isAxiosRequest` returns true, this function get axios request config from action
236getClientName | function | returns `action.payload.client` OR `'default'` | `M` `C` `A` | attempts to resolve used client name or use defaultClientName
237defaultClientName | every possible object key type | `'default'` | `M` | key which define client used if `getClienName` returned false value
238getRequestOptions | function | return `action.payload.options` | `M` `C` | returns options object from action to override some values
239interceptors | object `{request: [], response: []}` | | `M` `C` | You can pass axios request and response interceptors. Take care, first argument of interceptor is different from default axios interceptor, first received argument is object with `getState`, `dispatch` and `action` keys
240
241## License
242
243This project is licensed under the MIT license, Copyright (c) 2016 Michal Svrček. For more information see `LICENSE.md`.
244
245## Acknowledgements
246
247[Dan Abramov](https://github.com/gaearon) for Redux [Matt Zabriskie](https://github.com/mzabriskie) for [Axios](https://github.com/mzabriskie/axios). A Promise based HTTP client for the browser and node.js