A Better Way to Use Axios with Pinia Store for Handling API/HTTP Requests in Vue 3 Compositions API
In the realm of Vue 3 with compositions API, ensuring efficient HTTP request handling can be pivotal. In this article, we introduce a robust solution utilizing Axios and the Pinia Store for seamless API integration within Vue 3 projects.
Introduction:
With the evolving landscape of Vue 3 development, addressing the nuances of HTTP request management becomes essential. In our exploration, we encountered a lack of standardized documentation for integrating Axios with Vue 3 composition APIs. To bridge this gap, we crafted a solution that fosters scalability and maintainability across projects.
Implementation:
We kickstart our journey by establishing the foundational Pinia Store for Axios configuration. Leveraging Vue’s composition API, we define a dedicated store, encapsulating Axios configurations.
// useHttpStore.ts
import axios from 'axios'
import { onMounted, ref } from 'vue'
import { defineStore } from 'pinia'
export const useHttpStore = defineStore('useHttpStore', () => {
const http = ref(
axios.create({
baseURL: import.meta.env.VITE_API_URL,
withCredentials: true,
responseType: 'json',
headers: {
'Accept': 'application/json',
'Content-type': 'application/json'
}
})
)
return { http }
})
Error Handling and Service Layer:
Building upon the foundation laid by the Pinia Store, we establish a service layer for handling HTTP requests. Employing Vue 3’s composition API, we abstract request methods, integrating error-handling mechanisms for enhanced reliability.
// useHttpServiceStore.ts
import { defineStore } from 'pinia'
import { useHttpStore } from './useHttpStore'
import type { AxiosError, AxiosResponse } from 'axios'
import { useErrorModalStore } from '@/stores/useErrorModalStore'
import { useSpinnerStore } from '@/stores/useSpinnerStore'
import { useSnackBarStore } from '@/stores/useSnackBarStore'
export const useHttpServiceStore = defineStore('useHttpServiceStore', () => {
const { http } = useHttpStore()
const errorModalStore = useErrorModalStore()
const spinnerStore = useSpinnerStore()
const snackBarStore = useSnackBarStore()
function get(url: string, config = {}, snackBarText = ''): Promise<AxiosResponse | void | any> {
spinnerStore.showSpinner() // Optional (if we have a centralized loader to show)
return http
.get(url, config)
.then((response) => {
if (snackBarText) { // Optional, if we want to show SnackBar for some success responses (eg data update))
snackBarStore.showSnackBar(snackBarText)
}
return response?.data
})
.catch((error: AxiosError) => {
errorModalStore.showErrorModal(errorModalStore.title, error.message)
return false
})
.finally(() => {
spinnerStore.hideSpinner() // Optional
})
}
function post(
url: string,
data = {},
config = {},
snackBarText = ''
): Promise<AxiosResponse | void | any> {
spinnerStore.showSpinner() // Optional (if we have a centralized loader to show)
return http
.post(url, data, config)
.then((response) => {
if (snackBarText) { // Optional, if we want to show SnackBar for some success responses (eg data update))
snackBarStore.showSnackBar(snackBarText)
}
return response?.data
})
.catch((error: AxiosError) => {
errorModalStore.showErrorModal(errorModalStore.title, error.message)
return false
})
.finally(() => {
spinnerStore.hideSpinner() // Optional
})
}
return { get, post }
})
Conclusion:
Incorporating the Pinia Store with Axios empowers Vue 3 developers to streamline HTTP request handling with ease. By adopting this approach, projects benefit from enhanced maintainability and scalability, ensuring a seamless development experience.
Usage Example:
We illustrate the integration of the HTTP service store within a Vue 3 component, showcasing its utility in orchestrating API interactions.
// dashboard.vue
<template>
<div>
<h1>This is Dashboard page</h1>
</div>
</template>
<script lang="ts" setup>
import { onMounted } from 'vue'
import { useHttpServiceStore } from '@/stores/http/useHttpServiceStore'
import theRequestInterceptor from './theRequestInterceptor'
import theResponseInterceptor from './theResponseInterceptor'
const httpService = useHttpServiceStore()
onMounted(async () => {
theRequestInterceptor() // Optional
theResponseInterceptor() // Optional
const data = await httpService.get('/test_path')
console.log('data', data)
})
</script>
<style lang="scss">
</style>
Thank you for exploring this journey with us! Your feedback and insights are invaluable. Let’s elevate Vue 3 development together. ✨
Feel free to share your thoughts and insights in the comments below! 🚀