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
useRouter
usesprovide
/inject
to 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
useRouter
but this may result in module circular dependencies and this may not be work for other composables.createFetch
wasn'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
useApiFetchFn
depends on the implementation, in this case it's acceptable. At this point it may be more straightforward to useuseFetch
directly and compose the options similarly to howcreateFetch
does that, most of its code is dedicated to TS support and variadic arguments that may not be needed in this case.