I need to create a custom fetch composable from VueUse using createFetch() and I want to check if a request returns 401 status, I'd like the route to be redirected to the login route.
export const useApiFetch = createFetch({
baseUrl: import.meta.env.VITE_API_BASE_URL,
options: {
beforeFetch({ options }) {
const { user } = useSessionStore()
if (user)
options.headers.Authorization = `Basic ${user.user_id}:${user.password}`
return { options }
},
onFetchError(response) {
const route = useRoute()
const router = useRouter()
if (route.name !== 'login' && response.status === 401)
return router.push('/login')
}
}
})
But everytime it hits the error, useRoute and useRouter are undefined, and yes.. I have checked that it runs in setup
<script setup>
const submit = async () => {
const { error, data } = await useApiFetch('/login').post(form)
}
</script>
Did I miss something or is there a better way to do this? thanks
Vue composables are primarily expected to be called in setup block. Other usages depend on their implementation and needs to be confirmed. The main restriction is that a composable is linked to specific component instance, in this case
useRouterusesprovide/injectto get router instance through component hierarchy; this often can be be deduced without checking the actual implementation.It's possible to directly import router instance instead of using
useRouterbut this may result in module circular dependencies and this may not be work for other composables.createFetchwasn't designed for this usage and needs to be wrapped with custom composable that guarantees that other composables will be called in time:Whether it's correct to cache the result to
useApiFetchFndepends on the implementation, in this case it's acceptable. At this point it may be more straightforward to useuseFetchdirectly and compose the options similarly to howcreateFetchdoes that, most of its code is dedicated to TS support and variadic arguments that may not be needed in this case.