Redux Axios Middleware
Redux Axios Middleware is a Redux middleware designed to streamline data fetching using the popular Axios HTTP client within Redux applications. The current stable version is 4.0.1, with the last major release (v4.0.0) in March 2017, indicating a very slow release cadence, suggesting it's feature-complete or in maintenance mode rather than active development. Its key differentiators include directly integrating Axios request configurations into Redux actions, managing the full lifecycle of HTTP requests (start, success, error) with configurable action types and suffixes, and enabling promise chaining on dispatched actions for sequential logic or advanced error handling. It also supports defining and using multiple Axios clients for different APIs within a single Redux store.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'create')
cause Axios client was not provided as the first argument to `axiosMiddleware()` or was undefined.fixEnsure an initialized Axios instance is passed to the middleware: `axiosMiddleware(axios.create(...))`. -
Action with payload.request but missing type or types array.
cause An action was dispatched with `payload.request` but lacked either a `type` string or a `types` array, making it impossible for the middleware to determine subsequent action types.fixAdd either a `type: 'MY_ACTION_TYPE'` or `types: ['MY_REQUEST', 'MY_SUCCESS', 'MY_FAIL']` to your action object alongside `payload.request`. -
Error: Reducers may not dispatch actions while another action is dispatching.
cause Attempting to dispatch a new action directly within a reducer that's handling an action from `redux-axios-middleware`. This typically happens when trying to chain actions or handle side effects in reducers.fixHandle side effects and subsequent dispatches using the promise returned by `store.dispatch()` when using `redux-axios-middleware`, or by using other Redux side-effect libraries (e.g., `redux-thunk`, `redux-saga`).
Warnings
- breaking In version 4.0.0, the `action` parameter passed to interceptors was replaced by a `getSourceAction` function. Direct access to the triggering action via `action` parameter will no longer work.
- breaking Version 3.0 introduced changes to the default action prefixing logic. If you relied on the default prefixes for request, success, or error actions, they might have changed.
- gotcha Actions handled by `redux-axios-middleware` must contain a `payload.request` object defining the Axios request configuration. Actions without this structure will be ignored by the middleware.
- gotcha The middleware supports two action type definition patterns: a single `type` string (which will be suffixed by `_SUCCESS` or `_FAIL` by default) or an array of `types: [REQUEST_TYPE, SUCCESS_TYPE, FAILURE_TYPE]` for explicit control. Mixing these or misunderstanding their behavior can lead to incorrect action handling in reducers.
Install
-
npm install redux-axios-middleware -
yarn add redux-axios-middleware -
pnpm add redux-axios-middleware
Imports
- axiosMiddleware
import { axiosMiddleware } from 'redux-axios-middleware'; // Is a default exportimport axiosMiddleware from 'redux-axios-middleware';
- AxiosMiddlewareOptions
import type { AxiosMiddlewareOptions } from 'redux-axios-middleware'; - ReduxAxiosMiddleware (UMD)
<script src="https://unpkg.com/redux-axios-middleware/dist/bundle.js"></script>
Quickstart
import { createStore, applyMiddleware, combineReducers } from 'redux';
import axios from 'axios';
import axiosMiddleware from 'redux-axios-middleware';
// Create a basic Axios client instance
const client = axios.create({
baseURL: 'https://api.example.com',
responseType: 'json',
timeout: 5000
});
// Define a placeholder reducer (required by createStore)
const mockReducer = (state = {}, action) => {
console.log('Dispatched action:', action.type, action.payload || action.error);
return state;
};
// Combine reducers (even if just one for demonstration)
const reducers = combineReducers({
data: mockReducer
});
// Create the Redux store with the middleware
const store = createStore(
reducers,
applyMiddleware(axiosMiddleware(client))
);
// Action creator for loading categories
export function loadCategories() {
return {
type: 'LOAD_CATEGORIES',
payload: {
request: {
url: '/categories',
method: 'GET'
}
}
};
}
// Dispatch the action and handle the promise
store.dispatch(loadCategories())
.then(response => {
console.log('Categories loaded successfully:', response.payload.data);
})
.catch(error => {
console.error('Failed to load categories:', error.error);
});
// Example using `types` array for explicit action states
export function submitForm(formData) {
return {
types: ['SUBMIT_FORM_REQUEST', 'SUBMIT_FORM_SUCCESS', 'SUBMIT_FORM_FAILURE'],
payload: {
request: {
url: '/form-data',
method: 'POST',
data: formData
}
}
};
}
// Dispatch with custom types and chaining
const myFormData = { name: 'Test', value: 123 };
store.dispatch(submitForm(myFormData))
.then(() => console.log('Form submitted successfully!'))
.catch(error => console.error('Form submission failed:', error.error));