svrcekmichal / redux-axios-middleware Goto Github PK
View Code? Open in Web Editor NEWRedux middleware for fetching data with axios HTTP client
License: MIT License
Redux middleware for fetching data with axios HTTP client
License: MIT License
Hi, Thanks for this great package!. Need ask or maybe I doing it wrong.
I'm trying to setup the axiosmiddleware with interceptor. The interceptor request is working properly but the interceptor response not working.
here is my code:
function interceptorRequest(dispatch, config) {
const token = cookie.load('_t');
const configuration = config;
if (token) {
configuration.headers.Authorization = `Bearer ${cookie.load('_t')}`;
}
return configuration;
}
function interceptorResponse(dispatch, response) {
console.log(dispatch);
console.log(response);
console.log(error);
}
export const client = axios.create({
baseURL: API_URL,
headers: {
Accept: 'application/json',
},
});
export const clientOptions = {
interceptors: {
request: [interceptorRequest],
response: [interceptorResponse],
},
};
// store.js
// other import
import { client, clientOptions } from '../utils/axios';
const reduxRouterMiddleware = routerMiddleware(history);
const middlewares = [
thunk,
axiosMiddleware(client, clientOptions),
reduxRouterMiddleware,
];
const store = compose(applyMiddleware(...middlewares))(createStore)(reducer);
export default store;
my question:
// Add a request interceptor
axios.interceptors.request.use(function (config) {
// Do something before request is sent
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
// Add a response interceptor
axios.interceptors.response.use(function (response) {
// Do something with response data
return response;
}, function (error) {
// Do something with response error
return Promise.reject(error);
});
Thanks!
I'm using your middleware. But, when I use the action it does not work, says no token:
import axios from "axios";
import Cookie from "js-cookie";
import { API_BASE_URL } from '../config';
let token = Cookie.get('token') ? Cookie.get('token') : '';
export const api = axios.create({
baseURL: API_BASE_URL,
headers: {'Authorization': token}
});
export default api;
action:
export function userInfo() {
return {
type: types.USER_INFO,
payload: {
request: {
url: `/user-info/`,
method: "get"
}
}
};
}
in the login component I put the Cookie and go to the main page:
Cookie.set('token', 'Token '+ response.payload.data.token);
this.context.router.history.push('/');
And already on the main page do not work action. I can see Cookies in Aplication -> Cookies.
Only after rebooting the page everything works.
Can have to restart middleware config?
Thanks :)
Hello,
I recently created a repository which demonstrate how to use redux-axios-middleware using a typescript/react frontend and a .NET Core backend.
I think it could be interesting to give a link to this repository to people who want to see how it looks with a pure example. What do you think?
Please take a look here : https://github.com/Odonno/react-redux-axios-middleware-netcore-example
PS : More examples are coming but you can raise an issue if you see any mistake or if you have any suggestion.
I would like to be able to intercept a response error with a response error interceptor and still get the ${requestAction}_FAIL
action to be triggered. But it seems that the error just gets swallowed up whenever I add such an interceptor. Am I missing something?
For the moment, I'm just using onError
handler like this:
const middlewareConfig = {
onError: ({ action, error, next, dispatch }) => {
if (error.response.status === 401) {
dispatch(AuthActions.logout());
}
// propagate failure for further handling
const nextAction = {
type: `${action.type}_FAIL`,
error,
meta: {
previousAction: action,
},
};
next(nextAction);
return nextAction;
},
};
This issue/question arose from my previous #67. I struggle to get the action returned as a promise. As there is no example that I know of, I wanted to ask how it should be configured properly. right now I have (using typescript)
export const actionCreators = {
setCurrentRole: (id: number): AppThunkAction<KnownAction> => (dispatch, getState) => {
dispatch(new SetCurrentRole({ request: { url: `role/${id}/setCurrent`, method: "PUT" } }));
}
};
And then on my button I have
onClick={(e) => this.props.setCurrentRole(5)}
This however returns undefined (as it seems to be void function) not a promise as hinted by documentation
Props are injected by redux-connect. Code just for completness sake
export default connect<{
roles: RolesStore.RolesState
},
typeof RolesStore.actionCreators, SidebarAccountPropsCustom>(
(state: ApplicationState) => ({
roles: state.roles
}), // Selects which state properties are merged into the component's props
RolesStore.actionCreators // Selects which action creators are merged into the component's props
)(SidebarAccount);
These are my middlewares:
var middlewares: Middleware[] = [axiosMiddleware(client, axiosMiddlewareOptions), thunk, typedToPlain];
if (windowIfDefined) {
const loggerMiddleware = (createLogger as any)();
middlewares.push(loggerMiddleware);
if (history) {
middlewares.push(routerMiddleware(history));
}
}
axiosMiddlewareOptions just include setup for authentication.
Hope to get to the bottom of this, cheers!
I would like to simplify little bit default actions onSuccess
and onError
. My suggestion is:
export const onSuccess = ({ action, next, response }, options) => {
const nextAction = {
type: getActionTypes(action, options)[1],
payload: response,
meta: {
previousAction: action
}
};
next(nextAction);
return nextAction;
};
PROS:
This is the proposed error handler:
export const onError = ({ action, next, error }, options) => {
let errorObject;
if(error instanceof Error) {
errorObject = {
data: error.message,
status: 0
};
if(process.env.NODE_ENV !== 'production') {
console.log('HTTP Failure in Axios', error);
}
} else {
errorObject = error;
}
const nextAction = {
type: getActionTypes(action, options)[2],
error: errorObject,
meta: {
previousAction: action
}
};
next(nextAction);
return nextAction;
};
Error handler will handle HTTP Failure and create generic action error if something bad occured. It will also handle logging to console if not production env is used. After little bit of googling I found that code 0 may represent various http failures.
PROS:
When i dispatch action with type and request everything seems ok. I am transforming request with transformRequest and after request finish onSuccess and onError methods working well. But there is no action fires with '_SUCCESS' or '_ERROR' suffix. What could be my mistake?
return {
type: types.POST_LOGIN,
payload: {
request: {
url: '/users/login',
method: 'POST',
data: { username, password }
}
}
}
onSuccess: function (app) {
if (!app.response.data.Response && app.response.data.Header && app.response.data.Header.errors) {
return app.dispatch(actions.apiError(app.response.data.Header.errors));
}
app.dispatch(actions.ajaxReponse(app.response.data));
}
action Object {type: "AJAX_RESPONSE", data: Object}
isAxiosRequest
works with import { isAxiosRequest } from 'redux-axios-middleware/lib/defaults';
Neither working with import { isAxiosRequest } from 'redux-axios-middleware/src/defaults';
.
Nor with import { isAxiosRequest } from 'redux-axios-middleware/dist/bundle';
Also tried with import axiosMiddleware from 'redux-axios-middleware';
and then axiosMiddleware.isAxiosRequest(action)
lib
directory is ignored in git
.
src
directory is ignored in npm
.
How to use isAxiosRequest
?
Failing with isAxiosRequest(action)
Tried version 4.0.0, 3.1.1 and 3.0
May be I am missing something basic!
Hi, I'm currently looking for a way to reduce much duplicate code from my action creators and I think this project could help me.
I'm currently using redux-thunk
for all my async action creators. Is it possible to dispatch
a standard action when a request fails?
Can you implement or will you accept a PR adding a webpack build into the package for UMD support? This would be great for your package, for example, I wanted to realtime code demo the features today to a client using Cloud9 or Kobra.io but couldn't use this library with a script tag via https://unpkg.com/[email protected]/ because it's only built for commonJs.
Lets say that i have login
action like following.
export function login(credentials) {
return {
types: ['LOGIN','LOGIN_SUCCESS','LOGIN_ERROR'],
payload: {
request: {
url: '/api/login',
method: 'POST',,
data: credentials
}
}
}
}
When login is succeeded, i want to dispatch new action doAnother
.
How can i do that?
Do i need to do that in reducer when action.type = LOGIN_SUCCESS
?
I guess its anti-pattern, and there must be more redux-like approach.
Hi
I am working on a notification system for my app and was able to use onError and onSuccess hooks to dispatch additional actions like this:
import {onSuccess as defaultOnSuccess, onError as defaultOnError} from 'redux-axios-middleware/lib/defaults'
export const onSuccess = ({ action, next, response }, options) => {
if (action.messages && action.messages[1]) {
let message = action.messages[1]
if (typeof message == 'function') {
message = message(action)
}
next(notify(message, 'success'))
}
return defaultOnSuccess({action, next, response}, options)
};
export const onError = ({ action, next, error }, options) => {
if (action.messages && action.messages[2]) {
let message = action.messages[2]
if (typeof message == 'function') {
message = message(action)
}
next(notify(message, 'error'))
}
return defaultOnError({action, next, error}, options)
};
However, I cannot find any kind of onRequest handler to display the loading message. I can add another middleware, but it seems that it would make sense for redux-axios-middleware to have this
Hi,
I'm getting ^ that error from::
const axios = require('axios');
module.exports = {
client: axios.create({
baseURL: 'http://localhost:5000',
responseType: 'json',
// timeout: 5000,
}),
}
and in my action it looks like this::
export const GET_SHIT = 'GET_SHIT';
export function getShit() {
return {
type: GET_SHIT,
payload: {
request: {
method: "get",
url: "/getShit"
}
}
}
}
but i get an error that says ::
Uncaught TypeError: setupedClient.client.request is not a function
at eval (eval at <anonymous> (bundle.js:19090), <anonymous>:210:37)
at Object.eval [as getValue] (eval at <anonymous> (bundle.js:19930), <anonymous>:4:12)
at GettingShit.componentDidMount (eval at <anonymous> (bundle.js:7864), <anonymous>:91:18)
at CallbackQueue.notifyAll (eval at <anonymous> (bundle.js:6336), <anonymous>:76:22)
at ReactReconcileTransaction.close (eval at <anonymous> (bundle.js:17683), <anonymous>:80:26)
at ReactReconcileTransaction.closeAll (eval at <anonymous> (bundle.js:1804), <anonymous>:206:25)
at ReactReconcileTransaction.perform (eval at <anonymous> (bundle.js:1804), <anonymous>:153:16)
at batchedMountComponentIntoNode (eval at <anonymous> (bundle.js:6432), <anonymous>:126:15)
at ReactDefaultBatchingStrategyTransaction.perform (eval at <anonymous> (bundle.js:1804), <anonymous>:140:20)
at Object.batchedUpdates (eval at <anonymous> (bundle.js:17575), <anonymous>:62:26)
(anonymous) @ bundle.js?4fc5:210
(anonymous) @ bindActionCreators.js?d387:3
componentDidMount @ gettingShit.jsx?4b86:55
notifyAll @ CallbackQueue.js?1e54:76
close @ ReactReconcileTransaction.js?e1cc:80
closeAll @ Transaction.js?b216:206
perform @ Transaction.js?b216:153
batchedMountComponentIntoNode @ ReactMount.js?ccff:126
perform @ Transaction.js?b216:140
batchedUpdates @ ReactDefaultBatchingStrategy.js?1670:62
batchedUpdates @ ReactUpdates.js?89d4:97
_renderNewRootComponent @ ReactMount.js?ccff:320
_renderSubtreeIntoContainer @ ReactMount.js?ccff:401
render @ ReactMount.js?ccff:422
(anonymous) @ index.jsx?f515:42
(anonymous) @ bundle.js:7085
__webpack_require__ @ bundle.js:20
(anonymous) @ bundle.js:21865
__webpack_require__ @ bundle.js:20
(anonymous) @ bundle.js:66
(anonymous) @ bundle.js:69
the index file with this stuff is::
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import axiosMiddleware from 'redux-axios-middleware';
import promise from 'redux-promise';
import createMemoryHistory from 'history/createMemoryHistory';
import client from './utils/axiosconfig.js';
import store from './reducers/index.js';
const history = createMemoryHistory();
const createStoreWithMiddleware = applyMiddleware(axiosMiddleware(client), promise)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(store)}>
etc.etc.
is there something i'm doing wrong?
Hello! Many thanks to you for the work.
I have a question. Why is the response used next by default? In this case, the action with the request goes through the chain of middlewares only after redux-axios-middleware. Thus, if we do, for example, the middleware of authentification, we will have to:
As the redux-axios-middleware is caching configuration per name of the client it's not possible different store to be passed for testing unless different client is created for each test which sounds overwhelming.
Here is a sample test that illustrates the problem:
import axios from 'axios';
import axiosMiddleware from '../src/middleware';
import { expect } from 'chai';
import configureMockStore from 'redux-mock-store';
import MockAdapter from 'axios-mock-adapter';
const options = {
returnRejectedPromiseOnError: true,
interceptors: {
request: [
({ getState, dispatch }, config) => {
console.log('state in interceptor: ', getState());
config.headers['Authorization'] = 'Bearer ' + getState().access_token;
return config;
}
],
response: [
{
success: ({ dispatch }, response) => {
return response;
},
error: ({ dispatch, getSourceAction }, error) => {
return Promise.reject(error);
}
}
]
}
};
const middleware = axiosMiddleware(axios, options);
describe('axiosMiddleware', () => {
const mockAxiosClient = new MockAdapter(axios);
const mockStore = configureMockStore([middleware]);
const mockAdapter = mockAxiosClient.adapter();
afterEach(() => {
mockAxiosClient.reset();
});
after(() => {
mockAxiosClient.restore();
});
it('attaches authorization header on each request', () => {
let got;
mockAxiosClient.onGet('/test').reply(config => {
got = config.headers['Authorization'];
return [200];
});
const action = () => {
return {
type: 'LOAD',
payload: {
request: {
url: '/test'
}
}
};
};
const store = mockStore({ access_token: '::access_token::' });
return store.dispatch(action()).then(() => {
expect(got).to.equal('Bearer ::access_token::');
});
});
it('attaches another authorization header on each request', () => {
let got;
mockAxiosClient.onGet('/test2').reply(config => {
got = config.headers['Authorization'];
return [200];
});
const action = () => {
return {
type: 'ANOTHER_LOAD_ACTION',
payload: {
request: {
url: '/test2'
}
}
};
};
const store = mockStore({ access_token: '::another_access_token::' });
return store.dispatch(action()).then(() => {
expect(got).to.equal('Bearer ::another_access_token::');
});
});
});
The following test fails with:
1) axiosMiddleware attaches another authorization header on each request:
AssertionError: expected 'Bearer ::access_token::' to equal 'Bearer ::another_access_token::'
+ expected - actual
-Bearer ::access_token::
+Bearer ::another_access_token::
e.g the test of first test is used as it caches the store instance that was passed no matter that another store is created using mockStore.
As better feedback I've added few loggings in the interceptor too:
return ({ getState, dispatch }) => next => action => {
if (!middlewareOptions.isAxiosRequest(action)) {
return next(action);
}
console.log(`action: ${action.type}, store value: `, getState());
and this is the execution log:
axiosMiddleware
action: LOAD, store value: { access_token: '::access_token::' } -> this is in the middleware
state in interceptor: { access_token: '::access_token::' } -> this is in the interceptor
โ attaches authorization header on each request
action: ANOTHER_LOAD_ACTION, store value: { access_token: '::another_access_token::' } -> this is in the middleware
state in interceptor: { access_token: '::access_token::' } -> this is in the interceptor
Hello,
I'm hitting a bunch of road blocks trying to set a response from a axios.get
request to action payload. The main issue is that since the response is a promise it takes the entire promise as the payload and there is no way to set the response within the promise as the payload. Any advice on how to use this middleware to rectify the issue I am having?
I greatly appreciate any direction given and I thank you in advance.
Peter
I have a middleware which formats API responses. Is it possible to actions returned by calling .then
/.catch
on the request action to be put through that middleware?
Example:
action/login.js
export const logIn = (username, password) => {
const action = {
types: [LOG_IN, LOG_IN_SUCCESS, LOG_IN_FAIL],
payload: {
request: {
// request data
}
},
};
return dispatch => dispatch(action);
};
components/LogIn.js
class LogIn extends Component {
submitForm = (event) => {
const { logIn } = this.props;
const { username, password } = this.state;
event.preventDefault();
logIn(username, password)
.catch(failAction => console.log(failAction)) // <---
};
// render and stuff
}
failAction
is "raw" action, meaning it didn't go through the middleware. Is there a possiblity to change that, or is formatting manually each time the only option?
I'm struggling to understand the correct way to utilize this library. If I need to parse the returned response and do any sort of extraction/validation ... it seems, I have to handle response logic within the reducers (which doesn't seem right)? Moreover, I notice there are onSuccess/onError functions but no documentation on how or where to define and whether or not they are global on every request or per request (are they part of the middleware config or action). Overall, this needs improved documentation, is there any example application that utilizes this library so I can see if this fits the teams needs or whether to create our own middleware for handling request headers and JWT tokens?
Could someone provide a full example App using redux axios middleware?
Hello @svrcekmichal
I've confirmed that response interceptor is not working when the response's httpStatus code is not 200.
Otherwise it seems like working with 200 status codes.
Would you please check this?
Thanks,
Sergey
I am trying to have callbacks, but it's not working in the object:
type: ORDER_SUBMIT,
onSuccess({ getState, dispatch}){},
payload: {
request: {
method: 'put',
url: `/tickets/${orderData.orderTicketCode}`,
data: {}
},
onSuccess({ getState, dispatch }) {
},
meta: {
onSuccess({ getState, dispatch}) {
}
}
}
Where is the correct location?
Can we influence what the response returns as payload to the action?
For example I'm querying an API that returns a result with way more information that I needed, and I only want to use a single piece. Can I somehow filter after successfully receiving the raw response data, and sending only the data I need to the reducer with the _SUCCESS action?
I don't know if this is something that is related to the latest versions of axios.
But, when you state that:
const client = axios.create({ //all axios can be used, shown in axios documentation
baseUrl:'http://localhost:8080/api',
responseType: 'json'
});
The URL of baseUrl should be all capital letters, e.g. baseURL. This was something that made axios don't find the right property when it tries to check if there's any config parameter available with baseURL while creating the request object.
Best regards
Hi Guys thanks for the middleware library its really helpful.
Am facing issue when I receive success response from the server.
_FAIL works absolutely fine without error. But,
_SUCCESS is called and response is received as expected, but am getting a warning saying "possible unhandled promise Rejection (id: 1) TypeError: null is not a object (evaluating 'action.type') getStateForAction)"
Is it something you already faced, because promise is generated only by the middleware library for the action am performing.
Here is the config info:
const client = axios.create({ //all axios can be used, shown in axios documentation
baseURL: 'http://192.168.5.10/CoreServices/',
responseType: 'json'
});
const options = {
interceptors: {
request: [{
success: ({getState, dispatch, getSourceAction}, req) => {
if (getState() && getState().sessionReducer && getState().sessionReducer.token) {
req.headers['Authorization'] = 'Bearer ' + getState().sessionReducer.token
}
dispatch({
type: SHOW_LOADER
});
return req
},
error: ({getState, dispatch, getSourceAction}, req) => {
dispatch({
type: HIDE_LOADER
});
return Promise.reject(req);
}
}],
response: [{
success: ({getState, dispatch, getSourceAction}, res) => {
store.dispatch({
type: HIDE_LOADER
});
return res;
},
error: ({getState, dispatch, getSourceAction}, res) => {
store.dispatch({
type: HIDE_LOADER
});
return Promise.reject(res);
}
}]
}
};
switch (action.type) {
case `${LOGIN}`:
return {...state}
break;
case `${LOGIN}_SUCCESS`:
return {...state, isLoggedIn: true}
break;
case `${LOGIN}_FAIL`:
console.log('login failed!');
if(action.error &&
action.error.response &&
action.error.response.data &&
action.error.response.data.errors &&
Array.isArray(action.error.response.data.errors) &&
action.error.response.data.errors.length > 0) {
return {...state, isLoggedIn: false, error: action.error.response.data.errors[0].message}
} else {
return {...state, error: 'test error from backend'}
}
break;
case RESET_AUTHENTICATION_ERROR:
return {...state, error: null}
break;
default:
return {...state}
}
Please let me know if you have some info about this.
Have a case where an api do not return the correct error-status with request that fails, so I have added an interceptors in the axios-request
const client = axios.create({
baseURL: 'https://api.domain.com'
})
client.interceptors.response.use((response) => {
if (response.data && response.data.status && response.data.status === 'error') {
return Promise.reject(new Error(response.data.message || 'Request failed'))
}
return response
}, (error) => {
return Promise.reject(error)
})
This works fine with a plain axios, a request that contain a status-fields which is 'error', can be catched in the promise:
client.get('/auth/login', {
params: {
username: 'bar',
passord: 'foo'
}
}).then((data) => console.log('LOGIN OK', data))
.catch((error) => console.log('LOGIN ERROR', error.message))
With redux-axios-middleware I can get the action to fail with returnRejectedPromiseOnError
option in config:
const middleware = [
axiosMiddleware(client, {
returnRejectedPromiseOnError: true
})
]
But I also get a unhandled error in the console (which is not happening with the plain axios-setup)
HTTP Failure in Axios Error: Wrong username or passord.
at App.js:22
at tryCallOne (core.js:37)
at core.js:123
at JSTimers.js:295
at _callTimer (JSTimers.js:148)
at _callImmediatesPass (JSTimers.js:196)
at Object.callImmediates (JSTimers.js:464)
at MessageQueue.__callImmediates (MessageQueue.js:282)
at MessageQueue.js:137
at MessageQueue.__guard (MessageQueue.js:269)
Is this intended to work only for the request ? On my side calling getSourceAction by passing the response is returning undefined. Here is a sample snippet:
response: [
{
success: ({ dispatch, getSourceAction }, response) => {
console.log(getSourceAction(response))
return Promise.resolve(response)
},
error: ({ dispatch, getSourceAction }, error) => {
console.log(getSourceAction(error))
return Promise.reject(error)
}
}
]
What I'm trying to accomplish is refreshing of a token when it expires and server returns that request is not authorized.
Here is an example how this could be accomplished using axios interceptors: https://plnkr.co/edit/0ZLpc8jgKI18w4c0f905?p=preview
Hi. First of all, thanks for the effort that went into this. It's really a neatly done piece of code. Congrats!
Secondly, after using it for a little while, I seem to be starting to hit the limits of the api (maybe) and I was wondering if I am just doing something wrong, or if this is indeed not 100% suited for me.
My usecase:
I have to fire a request and then on success I have a to chain a few more requests after that. e.g. :
And here's where I struggle.
Firing action in reducer is obviously an anti pattern so I can't go that way.
Chaining of actions as described in readme would work (in my setup I don't get a promise for some reason so I am only speaking theoretically). The problem with this though is I can create this resource from many places . Chaining actions in UI seems therefore a bit too repetitive for comfort.
Am I missing something or would it make more sense for me to use pure axios with some defaults set?
Main reason why I went with this lib is ease of adding authorization and very neat config on the action side. Wouldn't want to lose that but I feel like I might have hit a limitation.
Thanks for your input!
Please update your README from this one:
const client = axios.create({ //all axios can be used, shown in axios documentation
baseURL:'http://localhost:8080/api',
responseType: 'json'
});
To this one:
const client = axios.create({ //all axios can be used, shown in axios documentation
baseURL:'http://localhost:8080/api',
options: {
responseType: 'json'
}
});
As I see from this line you use options for Axios from client.options
. So If I would like to use responseType
:json
I should put it to payload.options
or client.options
.
I just spent a lot of time on investigating why I receive the following error:
axios Failed to read the 'responseText' property from 'XMLHttpRequest': The value is only accessible if the object's 'response Type' is '' or 'text' (was 'json').
So the solution was just simple - put responseType:json
to client.options
.
For some reason when i have an action like USER/LOGIN
, i can't do anything like
yield takeEvery('USER/LOGIN_SUCCESS', mySaga);
However,
yield takeEvery('USER/LOGIN', mySaga);
in my saga works just fine, but obviously at the moment request is dispatched, not successfully finished.
I've added a monitoring reducer and USER/LOGIN_SUCCESS
is indeed dispatched, but takeEvery doesn't seem to care. Any ideas why?
I noticed in the document the default success and error suffix for action types are mentioned and exported from getActionTypes.js
. But in index.js
the 2 default suffix constants are not exported.
This makes developers to maintain 2 more hardcode constant in their code. However I wish I could use the default constants rather than hardcode.
Documentation for this options missing:
When the API return an error, return Promise.reject(newAction);
this line throw an uncaught exception. Which need to be caught like this store.dispatch(someAsyncAction).catch(err => err)
otherwise it will throw an Uncaught (in Promise) error. I think return newAction
is good enough there.
return client.request(options.getRequestConfig(action))
.then(
(response) => {
const newAction = options.onSuccess({ action, next, response, getState, dispatch }, options);
options.onComplete({ action: newAction, next, getState, dispatch }, options);
return newAction;
},
(error) => {
const newAction = options.onError({ action, next, error, getState, dispatch }, options);
options.onComplete({ action: newAction, next, getState, dispatch }, options);
return Promise.reject(newAction);
});
I set "Access-Control-Allow-Origin: *", but always get a warning:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
What do you guys think about adding a caching option for requests? We could implement an option w/ the cache to bypass cache if last request is older than age
or something along those lines... thoughts?
Hi,
I have a problem with asynchronous request and the succeeding success action not being passed on to the other middleware but being completely consumed by redux-axios-middleware.
I have a custom middleware that is taking care of access token handling and that is saving the access token on LOGIN_SUCCESS to a cookie. But the LOGIN_SUCCESS action does never reach the custom middleware. Can someone pls shed some light here ? From my understanding actions get passed through all middleware, right ?
Thanks for your help,
Alexander
How do I upload a file using this middleware and also track upload progress? Does anybody have an example?
I have used this in the past and it works really well for chaining promises.
Is is really nice to be able to call a then on your bound action creator to capture the response outside of your reducers. You can see their latest release notes.
I think it might be a really simple change if you want me to create a PR.
Hi,
I am considering using this instead of redux-sagas to manage all my api calls. Sagas makes it easy to test actions and dispatches.
What is the recommended way to test my app when using redux-axios-middleware to make api calls?
thanks,
Hi,
I was wondering how I could easily setup an interceptor that adds to requests headers an Authorization token excepted for some (like the one used to retrieve the token, etc..).
I'm asking you this since I couldn't find any way that allows the request intereceptor to get the proper action.
interceptors : {
request: [({ getState, dispatch, action }, config) => {
No matter what action is performed, only the first one called will persist here (in my case the AUTH action if i'm not already signed in).
I've read on different issue that this is related to the client instance, but honestly I'm totally lost now and I can't figure out what to do.
I'd really appreciate some help!
Thank for your great work too!
Regards,
Hi,
At docs I read at the section
Actions 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.
this.props.saveForm(formData)
.then(() => {
// router the user away
this.context.router.push("/my/home/page")
})
.catch((response) => {
//handle form errors
})
So , I want to tried with my simple form handler to handle error section
handleFormSubmit(data) {
this.props
.signIn(data)
.then((response) => {
})
.catch(response => {
console.log(response);
});
}
reducer:
export function signIn({ email, password }) {
return {
type: 'LOGIN',
payload: {
request: {
url: 'auth/login',
method: 'POST',
data: { email, password },
},
},
};
I want to tried error response to see if its working properly. But it never console it out (422, 401) response.
But If I move my console.log to then
section it will print it out properly.
Object {type: "LOGIN_FAIL", error: Error: Request failed with status code 422, meta: Object}
Why It enter to success response
instead of catch section (I removed all my response interceptor)?.
I'm using your great middleware! Thanks guys but:
when:
GameModal.react.js
async doCreateGame() {
const {
fields,
hideModal,
formDisabled,
} = this.props;
if (formDisabled) return;
try {
const response = await createGame(fields.$values());
console.log(response);
} catch (error) {
console.log(error);
}
}
Actions.js
export function createGame(fields) {
return {
types: ['CREATE_GAME','CREATE_GAME_SUCCESS','CREATE_GAME_ERROR'],
payload: {
request: {
url: '/api/game',
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
data: {
game_name: fields.game_name,
game_token: fields.game_token + "1-gtkoen",
destination_url: fields.destination_url
}
}
}
}
}
AxiosMiddlewareOptions
const axiosMiddlewareOptions = {
interceptors: {
request: [
(action, config) => {
if (action.getState().auth.accessToken) {
config.headers['x-access-token'] = action.getState().auth.accessToken
}
return config
}
]
}
}
axiosMiddleware(client, axiosMiddlewareOptions),
It returns this:
{
payload: {
request: {
data {
destination_url: 'url',
game_name: 'gname',
game_token: 'token'
},
headers {
Content-Type: 'application/json',
}
}
},
types: ['CREATE_GAME', 'CREATE_GAME_SUCCESS', 'CREATE_GAME_ERROR']
}
My question is:
Where is my x-auth-token and why i dont get response from url? Thanks :)
we're trying to send custom headers for NTML authentification purposes. I've tried this
const client = axios.create({ //all axios can be used, shown in axios documentation baseURL: 'http://1.2.3.4:8080', options: { responseType: 'json', SamAccount: 'username' } });
and
const client = axios.create({ //all axios can be used, shown in axios documentation baseURL: 'http://1.2.3.4:8080', options: { responseType: 'json', headers: { 'SamAccount': 'username' }; } });
but we're not seeing the headers change. the options property seems to be how it is done in the axios documentation... are there any other things that we should try?
First of all: thank you for creating this middleware!
Let's say I have a JWT token stored in the redux tree (fetched/generated on the login) that is needed for certain request to succeed - is it possible to somehow pass/use the token with this middleware?
I am following the same pattern used in the middleware-netcore-example. I see _FAIL constants in the app.ts actions file. I am attempting to send failures into state, but I am getting my wires crossed.
state:
export type App = { readonly values: { name: string, value: number }[] _readonly errors: [{ message: string, code: number }]_ };
action:
export type Action = { type: 'GET_VALUES_FAIL', payload: AxiosResponse } | ... };
reducer:
case Actions.GET_VALUES_FAIL: return { ...state, _errors_: action.payload.data };
Ideally i would map the fail action to a list of errors in the state..my app i have a error message action that ties into App.errors. Just not sure now to move forward given the errors live in a different object in state. How can i add this error data to my state?
How would you use this middleware with multiple APIs
Is this possible? I don't think it is but maybe we could name space axios clients?
Thoughts?
My GET is failing with redux-axios-middleware but when I make a simple call with what I believe is the same URL but with just an axios.get, it works. I think an interceptor will help me but I don't understand how to use it.
It would be really helpful if you could update the readme to include usage of the middlewareConfig you define in the readme.
I have the following code.
import axios from 'axios'
import axiosMiddleware from 'redux-axios-middleware'
const client = axios.create({
baseURL: 'http://api.dev',
responseType: 'json'
})
const options = {
successSuffix: 'success',
errorFix: 'error'
}
export default axiosMiddleware(client, options)
When I dispatch an action as { type: 'load' }
then I get { type: 'load_FAIL' }
. I expected to get { type: 'load_error' }
.
Idea is to allow passing options like returnRejectedPromiseOnError
to action.
{
type: 'LOAD',
payload: {
request:{
url:'/categories',
options: {
returnRejectedPromiseOnError: true
}
}
}
}
This way user can override client options in middleware setup. Options will be merged:
default options => middleware options => action options
Hi,
i'm trying to catch api error using axios-middleware
server is responding with 404 however, promise is resolved instead of beeing rejected.
note that it's wrapped with other promise:
this: is not working:
Keychain
.getGenericPassword()
.then((credentials) => {
return this.props.authProps(credentials.password).catch(() => {
// handle error
})
})
workaround for this is to check in then callback if there is error key
Keychain
.getGenericPassword()
.then((credentials) => {
return this.props.authProps(credentials.password).then((payload) => {
if(!payload.error) {
// handle error
}
})
Actions are dispatched correctly to store, just problem with this promise
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.