Using Axios in Nuxt with Composition API
Tags: vue, javascript, webdev, tutorial
Published: 2022-03-12 21:37:59

A common pattern when using [Axios](https://axios-http.com) 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](https://nuxtjs.org/) when using the [composition api](https://composition-api.nuxtjs.org/).

## Install Nuxt composition API

Since we'll be using the Vue.js composition API we'll install the [Nuxt plugin](https://composition-api.nuxtjs.org/) that will allow us to use the Vue 3 Composition API with Nuxt-specific features.

```bash
npm install @nuxtjs/composition-api
```

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

`nuxt.config.js`
```js
{
  ...
  buildModules: [
    '@nuxtjs/composition-api/module'
  ]
  ...
}
```

## 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.

```bash
npm install @nuxtjs/axios
```

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`
```js
{
  ...
  modules: [
    '@nuxtjs/axios'
  ],
  axios: {
    baseURL: 'https://reqres.in/api/',
  }
  ...
}
```

## 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](https://nuxtjs.org/docs/internals-glossary/context/) so that we can use it later in our functions as `$api` using the `useContext` composable.

`plugins/api.js`
```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)
}
```

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](https://axios.nuxtjs.org/helpers/). 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](https://reqres.in/) API in our example to setup two methods for fetching users.

> Notice how we're implementing our module as a [composable](https://vuejs.org/guide/reusability/composables.html) 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`
```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,
  }
}

```
**finally we can**
## Use the API functions inside our components
We can call our API function directly or use [useFetch](https://composition-api.nuxtjs.org/lifecycle/useFetch) or [useAsync](https://composition-api.nuxtjs.org/API/useAsync) depending on what we want to achieve.

```vue
<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>
```

**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](https://stackblitz.com/edit/nuxt-starter-baxkls?file=pages/index.vue) that demonstrates it in action.

Thanks for reading!