Skip to main content
kld.dev

Axios tips for real-world apps

Here are some helpful patterns and tips I have picked up for managing API requests with axios in your web app.

The Module

There are many examples online where an API endpoint URL is hard-coded into a component method or lifecycle hook.

There is nothing wrong with this, especially if you only have a few API endpoints. However, in a large application, it might be nice to create a module specifically for handling our requests.

Here is a typical example of a hard-coded axios request.

async function fetchData() {
  try {
    this.isLoading = true;
    const response = await axios.get('/api/items'); // <-------
    this.items = response.data;
  } catch (error) {
    // handle error
  } finally {
    this.isLoading = false;
  }
}

Let’s instead create our API module.

// api.js
import axios from 'axios';

export default {
  getItems: (params) => axios.get('/api/items', { params }),
  createItem: (item) => axios.post('/api/items', item),
  // etc.
};

Now we can easily see and update all of our endpoints in one file, and the rest of our app is less concerned with how or where we get our data.

import api from './api';

// Inside your async method, component lifecycle hook, etc.
const response = await api.getItems();

// We can use the same method with our optional params argument
const response = await api.getItems({ id: 9 });

If your API has many routes, it might make sense to organize your module into namespaces.

// api.js

const comments = {
  get: (params) => axios.get('/api/v2/comments', { params }),
  delete: (params) => axios.delete('/api/v2/comments', { params }),
  // etc.
};

const posts = {
  get: (params) => axios.get('/api/v2/posts', { params }),
  // etc.
};

export default {
  comments,
  posts,
};
const responses = await Promise.all(api.posts.get({ id }), api.comments.get({ postId: id }));

If you are a Vue user, and you find yourself importing your api module into many of your components, then consider adding it to the Vue prototype.

// main.js
import api from '@/api'
import Vue from 'vue'

// ...

Vue.prototype.$api = api

const app = new Vue({
// ...

Now all of your components will inherit that property as this.$api.

// MyComponent.vue
methods: {
  async getCat (id) {
    try {
      this.isLoading = true
      const { data } = await this.$api.getCat(id)
    } catch (error) {
      // handle error
    } finally {
      this.isLoading = false
    }
  }
}

The Base Route

We do not want to keep repeating our base route and version (/api/v2). To avoid that, our first option is to simply add some variables to a template string.

const version = '2';
const API = `/api/${version}`;

export default {
  getComments: (params) => axios.get(`${API}/comments`, params),
};

An even better option is to create an instance of axios that specifically targets our base route.

const API = axios.create({
  baseURL: '/api/v2',
});

export default {
  getComments: (params) => API.get('/comments', params),
};

Creating an axios instance can be especially handy if your API versioning is done with a header rather than the route. Just add a headers property to the config object for axios.create.

const API = axios.create({
  baseURL: '/api',
  headers: { 'Accept-Version': '~2' },
});

Your Application

Mix and match any or all of the above tips based on your needs for your app.

Maybe your Vue app does not need an API module, but you still want a global axios instance that targets your base route.

// main.js
import axios from 'axios'
import Vue from vue

const baseURL = '/api/v2'
Vue.prototype.$axios = axios.create({ baseURL })

// YourComponent.vue
this.$axios.post('/cats', data) // equivalent to axios.post('/api/v2/cats', data)

Be sure to explore the axios documentation some time as there are a lot of brilliant features. Thanks for reading!