-
Simple as that, how would one go about setting a default baseURL to be used by useFetch / useAsyncData? |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments 12 replies
-
I've been using a composable to create localized fetch requests, so in your case you can do something like this Add this composable And use it like this |
Beta Was this translation helpful? Give feedback.
-
Is there official way to do this? Should it be a nuxt plugin to create a fetch with neeed baseurl available globally? |
Beta Was this translation helpful? Give feedback.
-
TLDR: This all sucks I've been constantly running into issues, pinia complaining that it can't find an app, nuxt complaing that "A composable that requires access to the Nuxt instance was called outside of a plugin" or something the like. The earlier posted approach with the Previously I've used export const useApiFetch = async <
T = unknown,
R extends NitroFetchRequest = NitroFetchRequest,
>(
request: Parameters<typeof $fetch<T, R>>[0],
options?: Partial<Parameters<typeof $fetch<T, R>>[1]>,
) => {
return $fetch.create({
baseURL: useRuntimeConfig().public.BASE_URL,
headers: {
Authorization: `Bearer ${useAuthStore().token}`,
},
})(request, options);
}; but this is an abomination and results in Typescript complaining about Now I am using to get rid of the previous problems at the cost of having to call export const useApiFetch = () => {
return $fetch.create({
baseURL: useRuntimeConfig().public.BASE_URL,
headers: {
Authorization: `Bearer ${useAuthStore().token}`,
},
});
}; const res = await useApiFetch()<{firstname: string, lastname: string, email: string}>("/user", {
method: "GET",
}); btw this doesn't work, because nuxt doesnt like you accessing the runtime config and pinia doesn't like you accessing the store export const useApiFetch2 =
$fetch.create({
baseURL: useRuntimeConfig().public.apiBase,
headers: {
Authorization: `Bearer ${useAuthStore().token}`,
},
}); |
Beta Was this translation helpful? Give feedback.
-
May give a try to this one. This does the following things:
import { defu } from 'defu'
import { useFetch } from '#app'
type UseFetchOptions = Parameters<typeof useFetch>[1]
type UseAPIFetchOptions = UseFetchOptions & { protected?: boolean }
const isURL = (str: string) => {
try {
return Boolean(new URL(str))
}
catch {
return false
}
}
export const useAPIFetch: typeof useFetch = (
request,
opts: UseAPIFetchOptions = {},
) => {
const { public: { apiBaseURL } } = useRuntimeConfig()
const _nuxt = useNuxtApp()
const loadingIndicator = useLoadingIndicator()
const _opts: UseFetchOptions = {}
const _request = computed(() => {
const r = typeof request === 'function' ? request() : request
return toValue(r)
})
if (
!opts.baseURL
&& typeof _request.value === 'string'
&& !isURL(_request.value)
)
_opts.baseURL = apiBaseURL as string
if (opts.protected) {
const auth = useCookie('auth')
if (!auth) {
_nuxt.payload.error = createError({
statusCode: 401,
statusMessage: 'Unauthorized',
})
return
}
_opts.headers = { Authorization: `Bearer ${auth.value}` }
}
const options = defu(_opts, opts)
let abortController: AbortController | null = null
onBeforeUnmount(() => {
abortController?.abort()
})
return useFetch(request, {
onRequest: async ({ options }) => {
abortController?.abort()
abortController = new AbortController()
options.signal = abortController.signal
loadingIndicator.finish({ force: true }) // finish any previous loading
loadingIndicator.start()
},
onRequestError: async ({ error }) => {
loadingIndicator.finish()
console.error(error)
},
onResponse: async ({ response }) => {
loadingIndicator.finish()
return response._data
},
onResponseError: async ({ response }) => {
loadingIndicator.finish()
_nuxt.payload.error = createError({
statusCode: response.status,
statusMessage: `${response.statusText} ${response.url}`,
})
},
...options,
})
} |
Beta Was this translation helpful? Give feedback.
-
when researching this problem stumbled upon this post from the author of nuxt that answers this problem and provides insight into his thinking. credit alexander lichter's repo implementation for pointing me in this direction |
Beta Was this translation helpful? Give feedback.
-
this is a pretty simple solution for that: opts?: Omit<UseFetchOptions<T>, 'default'> & { default?: () => T | Ref<T> } |
Beta Was this translation helpful? Give feedback.
I've been using a composable to create localized fetch requests, so in your case you can do something like this
Add this composable
export const useBaseFetch = (url, options = {}) => $fetch(`/base-url${url}`, options)
And use it like this
const { data } = await useAsyncData('key', () => useBaseFetch('/data'))