Using axios globally in a Vue 3 with provide/inject (composition API)

Published 
Vue

In a Vue 2 we had to use Vue.prototype in order to add global properties to a Vue instance. But in a Vue 3 we got "Composition API".

So, using a composition api, recommended way to add global properties, is by using provide/inject. Because config.globalProperties considered as an escape hatch

Let's get started.

Create a file called http.ts (you can name it as you wish):

import axios, { AxiosInstance } from 'axios'

const apiClient: AxiosInstance = axios.create({
  baseURL: 'https://api.openbrewerydb.org',
  headers: {
    'Content-type': 'application/json'
  }
})

export default apiClient

It's our global Axios instance with the options.

Create a file symbols.ts

import { InjectionKey } from 'vue'
import { AxiosInstance } from 'axios'

export const AxiosKey: InjectionKey<AxiosInstance> = Symbol('http')

This is required to type our Provide/Inject.

Go to main.ts

// libs
import http from '@/http'
import { AxiosKey } from '@/symbols'

const app = createApp(App)

app.provide(AxiosKey, http)

We're providing our Axios instance globally here, using InjectionKey - AxiosKey, so it's typed now. Otherwise you would have to provide types every time you use inject()

Create a function to deal with undefined values, when you use inject():

import { inject, InjectionKey } from 'vue'

export function injectStrict<T>(key: InjectionKey<T>, fallback?: T) {
  const resolved = inject(key, fallback)
  if (!resolved) {
    throw new Error(`Could not resolve ${key.description}`)
  }
  return resolved
}

It was found in this useful blog post

Using our global axios instance inside a component:

<script setup lang="ts">
import { ref, onMounted } from 'vue'

// typing inject
import { injectStrict } from '@/utils/injectTyped'
import { AxiosKey } from '@/symbols'

interface Breweries {
  id: string
  name: string
}

const http = injectStrict(AxiosKey) // it's typed now
const breweries = ref<Breweries[]>([])

onMounted(async () => {
  const resp = await http.get<Breweries[]>('/breweries')
  breweries.value = resp.data
})
</script>