DEV Community

Cover image for Using Axios in Nuxt with Composition API
Giannis Koutsaftakis
Giannis Koutsaftakis

Posted on • Edited on

Using Axios in Nuxt with Composition API

A common pattern when using Axios in Vue.js apps, is to create a custom axios instance with interceptors attached in order to handle things (like e.g authentication and error reporting) globally.
We then use that instance in our API functions that are grouped inside files and/or folders depending on the business context.
Finally we import the API functions inside our components in order to fetch data.

Let's look at how we can implement the same pattern in Nuxt when using the composition api.

Install Nuxt composition API

Since we'll be using the Vue.js composition API we'll install the Nuxt plugin that will allow us to use the Vue 3 Composition API with Nuxt-specific features.

npm install @nuxtjs/composition-api
Enter fullscreen mode Exit fullscreen mode

Let's add it in nuxt.config.js inside the buildModules array.

nuxt.config.js

{
  ...
  buildModules: [
    '@nuxtjs/composition-api/module'
  ]
  ...
}
Enter fullscreen mode Exit fullscreen mode

Install, setup, and configure Nuxt Axios

We also need the nuxt/axios plugin which integrates Axios to Nuxt. There's no need to install axios as a standalone package, as the plugin takes care of that under the hood.

npm install @nuxtjs/axios
Enter fullscreen mode Exit fullscreen mode

We'll add it in nuxt.config.js inside the modules array.

We're also using the axios key in order to set some global options which will be applied to all requests. In this case we're only adding our API base URL as an example.

nuxt.config.js

{
  ...
  modules: [
    '@nuxtjs/axios'
  ],
  axios: {
    baseURL: 'https://reqres.in/api/',
  }
  ...
}
Enter fullscreen mode Exit fullscreen mode

Create and customize the Axios instance

In order to customize Axios by registering interceptors and changing global config, we have to create and register a Nuxt plugin. We are injecting our instance as api into the context so that we can use it later in our functions as $api using the useContext composable.

plugins/api.js

export default function ({ $axios, app }, inject) {
  const api = $axios.create()

  api.onRequest((config) => {
    console.log(`Making request to ${config.url}`)
  })

  api.onError((error) => {
    const code = parseInt(error.response && error.response.status)
    const errorText = code
      ? `A request failed with status code ${code}`
      : `A network error occurred`

    console.error(errorText)
  })

  api.onResponse((res) => {
    return res.data
  })

  inject('api', api)
}
Enter fullscreen mode Exit fullscreen mode

We can use the onRequest, onResponse, and onError helpers to intercept the request/response and handle errors respectively. Learn more about nuxt/axios helpers here. In our example we'll just use the onResponse helper to return the data from the response instead of the whole response object.

We are now ready to create our API functions and use them inside our Vue.js components

API functions

We are using the reqres API in our example to setup two methods for fetching users.

Notice how we're implementing our module as a composable so that it exports a function that returns an object with our data-fetching methods. We need to do this because useContext only works inside the Vue component's setup method.

api/user.js

import { useContext } from '@nuxtjs/composition-api'

export const userApi = () => {
  const { $api } = useContext()

  const fetchUser = async (userId) => {
    const res = await $api.get(`users/${userId}`)

    return res
  }

  const fetchUsers = async () => {
    const res = await $api.get('users')

    return res
  }

  return {
    fetchUser,
    fetchUsers,
  }
}

Enter fullscreen mode Exit fullscreen mode

finally we can

Use the API functions inside our components

We can call our API function directly or use useFetch or useAsync depending on what we want to achieve.

<template>
  <div>
    <div>
      <button type="button" class="btn btn-primary" @click="loadUsers">
        Fetch users
      </button>
    </div>
    <div>
      <pre>{{ users }}</pre>
    </div>
  </div>
</template>

<script>
import { defineComponent, ref } from '@nuxtjs/composition-api'
import { userApi } from '@/api/user'

export default defineComponent({
  setup() {
    const { fetchUsers } = userApi()
    const users = ref([])

    const loadUsers = async () => {
      const res = await fetchUsers()
      users.value = res.data
    }

    return {
      users,
      loadUsers,
    }
  },
})
</script>
Enter fullscreen mode Exit fullscreen mode

That was it, using this technique we can group our API calls in functions as we would do in a plain Vue.js app.

Here's a StackBlitz example that demonstrates it in action.

Thanks for reading!

Top comments (0)