Custom useFetch no Nuxt
Como criar um fetcher personalizado para chamar sua API externa no Nuxt.
Ao trabalhar com Nuxt, você pode estar desenvolvendo o frontend e buscando uma API externa, e pode querer definir algumas opções padrão para buscar da sua API.
A função utilitária $fetch
(usada pelo composable useFetch
) não é intencionalmente configurável globalmente. Isso é importante para que o comportamento de busca em toda a sua aplicação permaneça consistente, e outras integrações (como módulos) possam confiar no comportamento de utilitários principais como $fetch
.
No entanto, o Nuxt fornece uma maneira de criar um fetcher personalizado para sua API (ou múltiplos fetchers se você tiver várias APIs para chamar).
$fetch
Personalizado
Vamos criar uma instância personalizada de $fetch
com um plugin do Nuxt.
$fetch
é uma instância configurada de ofetch que suporta adicionar a URL base do seu servidor Nuxt, bem como chamadas de função direta durante SSR (evitando viagens HTTP).
Vamos supor aqui que:
- A API principal é https://api.nuxt.com
- Estamos armazenando o token JWT em uma sessão com nuxt-auth-utils
- Se a API responder com um código de status
401
, redirecionamos o usuário para a página/login
export default defineNuxtPlugin((nuxtApp) => {
const { session } = useUserSession()
const api = $fetch.create({
baseURL: 'https://api.nuxt.com',
onRequest({ request, options, error }) {
if (session.value?.token) {
// note que isso depende do ofetch >= 1.4.0 - você pode precisar atualizar seu lockfile
options.headers.set('Authorization', `Bearer ${session.value?.token}`)
}
},
async onResponseError({ response }) {
if (response.status === 401) {
await nuxtApp.runWithContext(() => navigateTo('/login'))
}
}
})
// Expor para useNuxtApp().$api
return {
provide: {
api
}
}
})
Com este plugin do Nuxt, $api
é exposto a partir de useNuxtApp()
para fazer chamadas de API diretamente dos componentes Vue:
const { $api } = useNuxtApp()
const { data: modules } = await useAsyncData('modules', () => $api('/modules'))
Envolver com useAsyncData
evita busca de dados duplicada ao fazer renderização do lado do servidor (servidor e cliente na hidratação).
useFetch
/useAsyncData
Personalizado
Agora que $api
tem a lógica que queremos, vamos criar um composable useAPI
para substituir o uso de useAsyncData
+ $api
:
import type { UseFetchOptions } from 'nuxt/app'
export function useAPI<T>(
url: string | (() => string),
options?: UseFetchOptions<T>,
) {
return useFetch(url, {
...options,
$fetch: useNuxtApp().$api as typeof $fetch
})
}
Vamos usar o novo composable e ter um componente agradável e limpo:
const { data: modules } = await useAPI('/modules')
Se você quiser personalizar o tipo de qualquer erro retornado, também pode fazê-lo:
import type { FetchError } from 'ofetch'
import type { UseFetchOptions } from 'nuxt/app'
interface CustomError {
message: string
statusCode: number
}
export function useAPI<T>(
url: string | (() => string),
options?: UseFetchOptions<T>,
) {
return useFetch<T, FetchError<CustomError>>(url, {
...options,
$fetch: useNuxtApp().$api
})
}
Este exemplo demonstra como usar um useFetch
personalizado, mas a mesma estrutura é idêntica para um useAsyncData
personalizado.
Atualmente estamos discutindo para encontrar uma maneira mais limpa de permitir que você crie um fetcher personalizado, veja https://github.com/nuxt/nuxt/issues/14736.
※Esta página é uma tradução não oficial da documentação oficial do Nuxt.js.
A página correspondente na documentação oficial está aqui:
https://nuxt.com/docs/3.x/guide/recipes/custom-usefetch