In my Vue 3 project, i use the composition API of Vue and i have axios defined as a plugin in plugins/axios.js
like this:
import axios from "axios";
import { useRouter } from "vue-router";
import { useErrorStore } from "../stores/error";
axios.interceptors.response.use(
(response) => {
return response;
},
(error) => {
const errorStore = useErrorStore();
errorStore.state.errors.push(error.response.data.detail);
if (parseInt(error.response.status) == 422) {
const router = useRouter();
router.push({
name: "login",
});
}
return Promise.reject(error);
}
);
export default axios;
ANTICIPATED BEHAVIOR: When the API call returns a 422 status, meaning the access token is invalid/ expired, the user shall be redirected to the login page.
PROBLEM:
router.push
does not work, i am not redirected when the error occurs. And i am not getting any error message on the console either.
On the other hand, the errorStore
as defined and accessed in the error case works just fine.
QUESTION: How can i redirect the user to another route from within the custom axios plugin file? Alternatively, is there a better/ more common way to achieve this?
Thanks for your help!
I'm going to answer this since it keeps coming up in Google searches and @Estus Flask's comments are correct.
You shouldn't use composables outside of script setup
tags. But in this case, a composable isn't necessary, as the router can be imported directly and still used as expected. So instead of...
import { useRouter } from 'vue-router';
const router = useRouter();
Directly import the router object that you have set up for your application startup. So, in @/router/index.js
, say you have something like this:
import { createRouter, createWebHistory } from 'vue-router';
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
// your routes here
]
});
export default router;
Then, in your Axios plugin, you would have something like this:
import axios from 'axios';
import router from '@/router';
axios.interceptors.response.use(
(response) => {
return response;
},
(error) => {
// whatever else you want to do with the error
router.push({ name: 'login' });
}
);
From my understanding, the router is a singleton and you will be using the constructed/live instance.