Axios middleware to use in all instances of axios Axios middleware to use in all instances of axios reactjs reactjs

Axios middleware to use in all instances of axios


As per the documentation - You need to create a file i.e

// api-client.jsimport axios from 'axios';// Add a request interceptoraxios.interceptors.request.use(function (config) {    // Do something before request is sent    console.log(config);    return config;  }, function (error) {    // Do something with request error    return Promise.reject(error);  });// Add a response interceptoraxios.interceptors.response.use(function (response) {    // Do something with response data    return response;  }, function (error) {    // Do something with response error    return Promise.reject(error);  });export default axios;

Then from your container or controller, import above file:

// Home.jsimport apiClient from './api-client.js';


Interceptors are the Axios way of doing this. For me though, it was too limited, tangled in Axios' API, difficult to test, etc.

Axios-middleware

So I wrote the axios-middleware module, a simple middleware service that hooks itself in your axios instance (either global or a local one) and provides a simple, self-contained and easily testable middleware API.

Note: it shines in bigger apps where minimal coupling is really important.

Simple example

Here's a simple example from the documentation

import axios from 'axios';import { Service } from 'axios-middleware';const service = new Service(axios);service.register({  onRequest(config) {    console.log('onRequest');    return config;  },  onSync(promise) {    console.log('onSync');    return promise;  },  onResponse(response) {    console.log('onResponse');    return response;  }});console.log('Ready to fetch.');// Just use axios like you would normally.axios('https://jsonplaceholder.typicode.com/posts/1')  .then(({ data }) => console.log('Received:', data));

It should output:

Ready to fetch.onRequestonSynconResponseReceived: {userId: 1, id: 1, title: ...

Testing a middleware

Say we have the following self-contained middleware class that we want to test.

export default class ApiErrorMiddleware {  constructor(toast) {    this.toast = toast;  }  onResponseError(err = {}) {    let errorKey = 'errors.default';    const { response } = err;    if (response && response.status) {      errorKey = `errors.${response.status}`;    } else if (err.message === 'Network Error') {      errorKey = 'errors.network-error';    }    this.toast.error(errorKey);    throw err;  }}

Then it's really easy, we don't even need to mock Axios.

import ApiErrorMiddleware from '@/middlewares/ApiErrorMiddleware';describe('ApiErrorMiddleware', () => {  let toast;  let middleware;  // Jest needs a function when we're expecting an error to be thrown.  function onResponseError(err) {    return () => middleware.onResponseError(err);  }  beforeEach(() => {    toast = { error: jest.fn() };    middleware = new ApiErrorMiddleware(toast);  });  it('sends a code error message', () => {    hasKey = true;    expect(onResponseError({ response: { status: 404 } })).toThrow();    expect(toast.error).toHaveBeenLastCalledWith('errors.404');  });});