mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-22 05:35:13 +00:00
refactor(nuxt): enhance useFetch
and useLazyFetch
request type (#4825)
Co-authored-by: Daniel Roe <daniel@roe.dev>
This commit is contained in:
parent
8298cf27e6
commit
3a822c7177
@ -10,7 +10,7 @@ Nuxt provides `useFetch`, `useLazyFetch`, `useAsyncData` and `useLazyAsyncData`
|
|||||||
|
|
||||||
Within your pages, components and plugins you can use `useFetch` to universally fetch from any URL.
|
Within your pages, components and plugins you can use `useFetch` to universally fetch from any URL.
|
||||||
|
|
||||||
This composable provides a convenient wrapper around `useAsyncData` and `$fetch`. It automatically generates a key based on URL and fetch options, as well as infers API response type.
|
This composable provides a convenient wrapper around `useAsyncData` and `$fetch`. It automatically generates a key based on URL and fetch options, provides type hints for request url based on server routes, and infers API response type.
|
||||||
|
|
||||||
::ReadMore{link="/api/composables/use-fetch"}
|
::ReadMore{link="/api/composables/use-fetch"}
|
||||||
::
|
::
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# `useFetch`
|
# `useFetch`
|
||||||
|
|
||||||
This composable provides a convenient wrapper around [`useAsyncData`](/api/composables/use-async-data) and [`$fetch`](/api/utils/$fetch). It automatically generates a key based on URL and fetch options, as well as infers API response type.
|
This composable provides a convenient wrapper around [`useAsyncData`](/api/composables/use-async-data) and [`$fetch`](/api/utils/$fetch). It automatically generates a key based on URL and fetch options, provides type hints for request url based on server routes, and infers API response type.
|
||||||
|
|
||||||
## Type
|
## Type
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { FetchOptions, FetchRequest } from 'ohmyfetch'
|
import type { FetchOptions } from 'ohmyfetch'
|
||||||
import type { TypedInternalResponse, NitroFetchRequest } from 'nitropack'
|
import type { TypedInternalResponse, NitroFetchRequest } from 'nitropack'
|
||||||
import { computed, isRef, Ref } from 'vue'
|
import { computed, isRef, Ref } from 'vue'
|
||||||
import type { AsyncDataOptions, _Transform, KeyOfRes, AsyncData, PickFrom } from './asyncData'
|
import type { AsyncDataOptions, _Transform, KeyOfRes, AsyncData, PickFrom } from './asyncData'
|
||||||
@ -48,11 +48,11 @@ export function useFetch<
|
|||||||
const key = '$f' + _key
|
const key = '$f' + _key
|
||||||
|
|
||||||
const _request = computed(() => {
|
const _request = computed(() => {
|
||||||
let r = request as Ref<FetchRequest> | FetchRequest | (() => FetchRequest)
|
let r = request
|
||||||
if (typeof r === 'function') {
|
if (typeof r === 'function') {
|
||||||
r = r()
|
r = r()
|
||||||
}
|
}
|
||||||
return (isRef(r) ? r.value : r) as NitroFetchRequest
|
return (isRef(r) ? r.value : r)
|
||||||
})
|
})
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -85,7 +85,7 @@ export function useFetch<
|
|||||||
}
|
}
|
||||||
|
|
||||||
const asyncData = useAsyncData<_ResT, ErrorT, Transform, PickKeys>(key, () => {
|
const asyncData = useAsyncData<_ResT, ErrorT, Transform, PickKeys>(key, () => {
|
||||||
return $fetch(_request.value, _fetchOptions)
|
return $fetch(_request.value, _fetchOptions) as Promise<_ResT>
|
||||||
}, _asyncDataOptions)
|
}, _asyncDataOptions)
|
||||||
|
|
||||||
return asyncData
|
return asyncData
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { withQuery } from 'ufo'
|
import { withQuery } from 'ufo'
|
||||||
import type { NitroErrorHandler, NitroFetchRequest } from 'nitropack'
|
import type { NitroErrorHandler } from 'nitropack'
|
||||||
// @ts-ignore TODO
|
// @ts-ignore TODO
|
||||||
import { normalizeError, isJsonRequest } from '#internal/nitro/utils'
|
import { normalizeError, isJsonRequest } from '#internal/nitro/utils'
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ export default <NitroErrorHandler> async function errorhandler (_error, event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HTML response
|
// HTML response
|
||||||
const url = withQuery('/__nuxt_error', errorObject as any) as NitroFetchRequest
|
const url = withQuery('/__nuxt_error', errorObject as any)
|
||||||
const html = await $fetch(url).catch((error) => {
|
const html = await $fetch(url).catch((error) => {
|
||||||
console.error('[nitro] Error while generating error response', error)
|
console.error('[nitro] Error while generating error response', error)
|
||||||
return errorObject.statusMessage
|
return errorObject.statusMessage
|
||||||
|
14
test/fixtures/basic/types.ts
vendored
14
test/fixtures/basic/types.ts
vendored
@ -135,6 +135,20 @@ describe('composables', () => {
|
|||||||
expectTypeOf(useFetch('/test', { default: () => 500 }).data).toMatchTypeOf<Ref<number>>()
|
expectTypeOf(useFetch('/test', { default: () => 500 }).data).toMatchTypeOf<Ref<number>>()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('infer request url string literal from server/api routes', () => {
|
||||||
|
// request can accept dynamic string type
|
||||||
|
const dynamicStringUrl:string = 'https://example.com/api'
|
||||||
|
expectTypeOf(useFetch(dynamicStringUrl).data).toMatchTypeOf<Ref<Pick<unknown, never>>>()
|
||||||
|
|
||||||
|
// request param should infer string literal type / show auto-complete hint base on server routes, ex: '/api/hello'
|
||||||
|
expectTypeOf(useFetch('/api/hello').data).toMatchTypeOf<Ref<string>>()
|
||||||
|
expectTypeOf(useLazyFetch('/api/hello').data).toMatchTypeOf<Ref<string>>()
|
||||||
|
|
||||||
|
// request can accept string literal and Request object type
|
||||||
|
expectTypeOf(useFetch('https://example.com/api').data).toMatchTypeOf<Ref<Pick<unknown, never>>>()
|
||||||
|
expectTypeOf(useFetch(new Request('test')).data).toMatchTypeOf<Ref<Pick<unknown, never>>>()
|
||||||
|
})
|
||||||
|
|
||||||
it('provides proper type support when using overloads', () => {
|
it('provides proper type support when using overloads', () => {
|
||||||
expectTypeOf(useState('test')).toMatchTypeOf(useState())
|
expectTypeOf(useState('test')).toMatchTypeOf(useState())
|
||||||
expectTypeOf(useState('test', () => ({ foo: Math.random() }))).toMatchTypeOf(useState(() => ({ foo: Math.random() })))
|
expectTypeOf(useState('test', () => ({ foo: Math.random() }))).toMatchTypeOf(useState(() => ({ foo: Math.random() })))
|
||||||
|
Loading…
Reference in New Issue
Block a user