nuxt logo

Tradução da Documentação (Não Oficial)

Nuxt.js
Version:v3.17

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
plugins/api.ts
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:

app.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:

composables/useAPI.ts
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:

app.vue
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.

Editar e visualizar o código de exemploexamples > advanced > use-custom-fetch-composable

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.