DEV Community

Alexander Kim
Alexander Kim

Posted on • Edited on

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

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.

1. 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
Enter fullscreen mode Exit fullscreen mode

It's our global Axios instance with the options.

2. Create a file symbols.ts

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

export const AxiosKey: InjectionKey<AxiosInstance> = Symbol('http')
Enter fullscreen mode Exit fullscreen mode

This is required to type our Provide/Inject.

3. Go to main.ts

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

const app = createApp(App)

app.provide(AxiosKey, http)
Enter fullscreen mode Exit fullscreen mode

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()

4. 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
}
Enter fullscreen mode Exit fullscreen mode

It was found in this useful blog post

5. 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>
Enter fullscreen mode Exit fullscreen mode

Top comments (3)

Collapse
 
isimmons profile image
Ian Simmons

Great Demo. Thanks

Collapse
 
bobl profile image
Bob Lefevre

Excellent article that stopped me pulling my hair - thanks!

Collapse
 
pdmshrestha profile image
Padam Shrestha

What would be the best approach to use same axios instance on .js file with inject?