useFetch
Этот композабл — удобная обёртка над useAsyncData и $fetch.
Он сам строит ключ из URL и параметров запроса, подсказывает типы для URL по серверным маршрутам и выводит тип ответа API.
useFetch вызывают напрямую в setup, плагине или прослойке маршрута (middleware). Он возвращает реактивные ссылки и кладёт ответ в payload Nuxt, чтобы при гидратации не запрашивать те же данные на клиенте повторно.Использование
<script setup lang="ts">
const { data, status, error, refresh, clear } = await useFetch('/api/modules', {
pick: ['title'],
})
</script>
useFetch, не используйте await внутри неё — это может дать непредсказуемое поведение. См. рецепт про пользовательский useFetch/useAsyncData.data, status и error — это ref из Vue; к ним следует обращаться через .value внутри <script setup>, а refresh/execute и clear — обычные функции.Используя свойство query, вы можете добавить параметры поиска в запрос. Эта опция расширена из unjs/ofetch и использует unjs/ufo для создания URL. Объекты автоматически превращаются в строку.
const param1 = ref('value1')
const { data, status, error, refresh } = await useFetch('/api/modules', {
query: { param1, param2: 'value2' },
})
В результате приведённого выше примера получится https://api.nuxt.com/modules?param1=value1¶m2=value2.
Вы также можете использовать перехватчики:
const { data, status, error, refresh, clear } = await useFetch('/api/auth/login', {
onRequest ({ request, options }) {
// Устанавливает заголовки запроса
// нужен ofetch >= 1.4.0 — при необходимости обновите lockfile
options.headers.set('Authorization', '...')
},
onRequestError ({ request, options, error }) {
// Обрабатывает ошибки запроса
},
onResponse ({ request, response, options }) {
// Обрабатывает данные ответа
localStorage.setItem('token', response._data.token)
},
onResponseError ({ request, response, options }) {
// Обрабатывает ошибки ответа
},
})
Реактивный URL и общее состояние
URL может быть computed, обычным ref или функцией — данные обновятся при смене адреса:
<script setup lang="ts">
const route = useRoute()
const id = computed(() => route.params.id)
// При смене маршрута и обновлении id данные перезапросятся автоматически
const { data: post } = await useFetch(() => `/api/posts/${id.value}`)
</script>
При одинаковом URL и опциях в нескольких компонентах общие data, error и status — состояние согласовано между ними.
useFetch доступно в приложении через useNuxtData.useFetch — зарезервированное имя, которое обрабатывает компилятор; свою функцию так называть нельзя.data, деструктурированная из useFetch, возвращает строку, а не разобранный JSON-объект, убедитесь, что ваш компонент не включает оператор импорта, подобный import { useFetch } from '@vueuse/core'.Реактивные опции запроса
Опции запроса могут быть реактивными: computed, ref и вычисляемые геттеры. При изменении реактивной опции выполняется повторный запрос с актуальным значением.
const searchQuery = ref('initial')
const { data } = await useFetch('/api/search', {
query: { q: searchQuery },
})
// повторный запрос: /api/search?q=new%20search
searchQuery.value = 'new search'
Отключить это поведение можно через watch: false:
const searchQuery = ref('initial')
const { data } = await useFetch('/api/search', {
query: { q: searchQuery },
watch: false,
})
// повторного запроса не будет
searchQuery.value = 'new search'
Тип
export function useFetch<DataT, ErrorT> (
url: string | Request | Ref<string | Request> | (() => string | Request),
options?: UseFetchOptions<DataT>,
): Promise<AsyncData<DataT, ErrorT>>
type UseFetchOptions<DataT> = {
key?: MaybeRefOrGetter<string>
method?: MaybeRefOrGetter<string>
query?: MaybeRefOrGetter<SearchParams>
params?: MaybeRefOrGetter<SearchParams>
body?: MaybeRefOrGetter<RequestInit['body'] | Record<string, any>>
headers?: MaybeRefOrGetter<Record<string, string> | [key: string, value: string][] | Headers>
baseURL?: MaybeRefOrGetter<string>
cache?: false | 'default' | 'force-cache' | 'no-cache' | 'no-store' | 'only-if-cached' | 'reload'
server?: boolean
lazy?: boolean
immediate?: boolean
getCachedData?: (key: string, nuxtApp: NuxtApp, ctx: AsyncDataRequestContext) => DataT | undefined
deep?: boolean
dedupe?: 'cancel' | 'defer'
timeout?: number
default?: () => DataT
transform?: (input: DataT) => DataT | Promise<DataT>
pick?: string[]
$fetch?: typeof globalThis.$fetch
watch?: MultiWatchSources | false
timeout?: MaybeRefOrGetter<number>
}
type AsyncDataRequestContext = {
/** Причина этого запроса данных */
cause: 'initial' | 'refresh:manual' | 'refresh:hook' | 'watch'
}
type AsyncData<DataT, ErrorT> = {
data: Ref<DataT | null>
pending: Ref<boolean>
refresh: (opts?: AsyncDataExecuteOptions) => Promise<void>
execute: (opts?: AsyncDataExecuteOptions) => Promise<void>
clear: () => void
error: Ref<ErrorT | null>
status: Ref<AsyncDataRequestStatus>
}
interface AsyncDataExecuteOptions {
dedupe?: 'cancel' | 'defer'
timeout?: number
signal?: AbortSignal
}
type AsyncDataRequestStatus = 'idle' | 'pending' | 'success' | 'error'
Параметры
URL(string | Request | Ref<string | Request> | () => string | Request): URL или объектRequest. Может быть строкой,Request, ref Vue или функцией; поддерживается реактивность.options(object): настройки запроса. Расширяет unjs/ofetch иAsyncDataOptions. Любая опция может быть константой,refилиcomputed.
| Опция | Тип | По умолчанию | Описание |
|---|---|---|---|
key | MaybeRefOrGetter<string> | авто | Уникальный ключ дедупликации; если не задан — из URL и опций. |
method | string | 'GET' | HTTP-метод. |
query | object | - | Параметры строки запроса. Псевдоним: params. Поддержка ref/computed. |
params | object | - | То же, что query. |
body | RequestInit['body'] | Record<string, any> | - | Тело запроса; объекты сериализуются. Поддержка ref/computed. |
headers | Record<string, string> | [key, value][] | Headers | - | Заголовки. |
baseURL | string | - | Базовый URL. |
timeout | number | - | Таймаут в мс до отмены запроса. |
cache | boolean | string | - | Кэш: false отключает или значения Fetch API: default, no-store и т.д. |
server | boolean | true | Выполнять ли запрос на сервере. |
lazy | boolean | false | При true — после загрузки маршрута (не блокирует навигацию). |
immediate | boolean | true | При false запрос не стартует сразу. |
default | () => DataT | - | Значение data до завершения асинхронной части. |
transform | (input: DataT) => DataT | Promise<DataT> | - | Преобразование результата после получения. |
getCachedData | (key, nuxtApp, ctx) => DataT | undefined | - | Возврат кэшированных данных; см. значение по умолчанию ниже. |
pick | string[] | - | Оставить в результате только перечисленные ключи. |
watch | MultiWatchSources | false | - | Реактивные источники для автообновления; false отключает. |
deep | boolean | false | Глубокий ref; при false — поверхностный (shallow), быстрее, если глубокая реактивность не нужна. |
dedupe | 'cancel' | 'defer' | 'cancel' | Не дублировать запросы с одним ключом. |
$fetch | typeof globalThis.$fetch | - | Своя реализация $fetch. |
computed или ref — при изменении выполнится новый запрос.Значение getCachedData по умолчанию:
const getDefaultCachedData = (key, nuxtApp, ctx) => nuxtApp.isHydrating
? nuxtApp.payload.data[key]
: nuxtApp.static.data[key]
Кэширование срабатывает только при включённом experimental.payloadExtraction в nuxt.config.
Возвращаемое значение
| Имя | Тип | Описание |
|---|---|---|
data | Ref<DataT | undefined> | Результат асинхронного запроса. |
refresh | (opts?: AsyncDataExecuteOptions) => Promise<void> | Ручное обновление. По умолчанию Nuxt ждёт завершения текущего refresh перед следующим вызовом. |
execute | (opts?: AsyncDataExecuteOptions) => Promise<void> | Синоним refresh. |
error | Ref<ErrorT | undefined> | Ошибка, если запрос не удался. |
status | Ref<'idle' | 'pending' | 'success' | 'error'> | Статус запроса (см. ниже). |
pending | Ref<boolean> | true, пока запрос выполняется. |
clear | () => void | Сброс data в undefined (или options.default()), error в undefined, status в idle, отмена ожидающих запросов. |
Значения status
idle: запрос ещё не начался (например,{ immediate: false }или{ server: false }при SSR)pending: запрос выполняетсяsuccess: успехerror: ошибка
server: false), они не загрузятся до завершения гидратации. Даже при await useFetch на клиенте в <script setup>data может оставаться null.