From 78cfbdd0cf1abcb68ab865c5b5691c2918276b66 Mon Sep 17 00:00:00 2001 From: Przemek Brzosko <67122459+pbrzosko@users.noreply.github.com> Date: Tue, 14 Mar 2023 18:31:03 +0200 Subject: [PATCH] feat(useFetch): update data on success (#2711) Co-authored-by: Przemyslaw Brzosko --- packages/core/useFetch/index.test.ts | 48 ++++++++++++++-------------- packages/core/useFetch/index.ts | 20 ++++++------ 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/packages/core/useFetch/index.test.ts b/packages/core/useFetch/index.test.ts index e7efc1c0335..58e2721291c 100644 --- a/packages/core/useFetch/index.test.ts +++ b/packages/core/useFetch/index.test.ts @@ -200,20 +200,20 @@ describe('useFetch', () => { baseUrl: 'https://example.com', options: { onFetchError(ctx) { - ctx.data.title = 'Global' + ctx.error = 'Global' return ctx }, }, }) - const { data } = useMyFetch('test?status=400&json', { + const { error } = useMyFetch('test?status=400&json', { onFetchError(ctx) { - ctx.data.title += ' Local' + ctx.error += ' Local' return ctx }, }).json() await retry(() => { - expect(data.value).toEqual(expect.objectContaining({ title: 'Global Local' })) + expect(error.value).toEqual('Global Local') }) }) @@ -272,23 +272,23 @@ describe('useFetch', () => { baseUrl: 'https://example.com', options: { onFetchError(ctx) { - ctx.data.title = 'Global' + ctx.error = 'Global' return ctx }, }, }) - const { data } = useMyFetch( + const { error } = useMyFetch( 'test?status=400&json', { method: 'GET' }, { onFetchError(ctx) { - ctx.data.title += ' Local' + ctx.error += ' Local' return ctx }, }).json() await retry(() => { - expect(data.value).toEqual(expect.objectContaining({ title: 'Global Local' })) + expect(error.value).toEqual('Global Local') }) }) @@ -345,21 +345,20 @@ describe('useFetch', () => { combination: 'overwrite', options: { onFetchError(ctx) { - ctx.data.global = 'Global' + ctx.error = 'Global' return ctx }, }, }) - const { data } = useMyFetch('test?status=400&json', { + const { error } = useMyFetch('test?status=400&json', { onFetchError(ctx) { - ctx.data.local = 'Local' + ctx.error = 'Local' return ctx }, }).json() await retry(() => { - expect(data.value).toEqual(expect.objectContaining({ local: 'Local' })) - expect(data.value).toEqual(expect.not.objectContaining({ global: 'Global' })) + expect(error.value).toEqual('Local') }) }) @@ -422,24 +421,23 @@ describe('useFetch', () => { combination: 'overwrite', options: { onFetchError(ctx) { - ctx.data.global = 'Global' + ctx.error = 'Global' return ctx }, }, }) - const { data } = useMyFetch( + const { error } = useMyFetch( 'test?status=400&json', { method: 'GET' }, { onFetchError(ctx) { - ctx.data.local = 'Local' + ctx.error = 'Local' return ctx }, }).json() await retry(() => { - expect(data.value).toEqual(expect.objectContaining({ local: 'Local' })) - expect(data.value).toEqual(expect.not.objectContaining({ global: 'Global' })) + expect(error.value).toEqual('Local') }) }) @@ -537,23 +535,24 @@ describe('useFetch', () => { }) test('should run the onFetchError function', async () => { - const { data, statusCode } = useFetch('https://example.com?status=400&json', { + const { data, error, statusCode } = useFetch('https://example.com?status=400&json', { onFetchError(ctx) { - ctx.data.title = 'Hunter x Hunter' + ctx.error = 'Internal Server Error' return ctx }, }).json() await retry(() => { expect(statusCode.value).toEqual(400) - expect(data.value).toEqual(expect.objectContaining({ title: 'Hunter x Hunter' })) + expect(error.value).toEqual('Internal Server Error') + expect(data.value).toBeNull() }) }) test('should run the onFetchError function when network error', async () => { - const { data, statusCode } = useFetch('https://example.com?status=500&text=Internal%20Server%20Error', { + const { data, error, statusCode } = useFetch('https://example.com?status=500&text=Internal%20Server%20Error', { onFetchError(ctx) { - ctx.data = { title: 'Hunter x Hunter' } + ctx.error = 'Internal Server Error' return ctx }, @@ -561,7 +560,8 @@ describe('useFetch', () => { await retry(() => { expect(statusCode.value).toStrictEqual(500) - expect(data.value).toEqual({ title: 'Hunter x Hunter' }) + expect(error.value).toEqual('Internal Server Error') + expect(data.value).toBeNull() }) }) diff --git a/packages/core/useFetch/index.ts b/packages/core/useFetch/index.ts index 4bfc40a0525..4a050f88da8 100644 --- a/packages/core/useFetch/index.ts +++ b/packages/core/useFetch/index.ts @@ -26,7 +26,7 @@ export interface UseFetchReturn { error: Ref /** - * The fetch response body, may either be JSON or text + * The fetch response body on success, may either be JSON or text */ data: Ref @@ -349,7 +349,7 @@ export function useFetch(url: MaybeComputedRef, ...args: any[]): UseF const statusCode = ref(null) const response = shallowRef(null) const error = shallowRef(null) - const data = shallowRef(initialData) + const data = shallowRef(initialData || null) const canAbort = computed(() => supportsAbort && isFetching.value) @@ -441,14 +441,15 @@ export function useFetch(url: MaybeComputedRef, ...args: any[]): UseF responseData = await fetchResponse[config.type]() - if (options.afterFetch && statusCode.value >= 200 && statusCode.value < 300) - ({ data: responseData } = await options.afterFetch({ data: responseData, response: fetchResponse })) - - data.value = responseData - // see: https://www.tjvantoll.com/2015/09/13/fetch-and-errors/ - if (!fetchResponse.ok) + if (!fetchResponse.ok) { + data.value = initialData || null throw new Error(fetchResponse.statusText) + } + + if (options.afterFetch) + ({ data: responseData } = await options.afterFetch({ data: responseData, response: fetchResponse })) + data.value = responseData responseEvent.trigger(fetchResponse) return resolve(fetchResponse) @@ -457,8 +458,7 @@ export function useFetch(url: MaybeComputedRef, ...args: any[]): UseF let errorData = fetchError.message || fetchError.name if (options.onFetchError) - ({ data: responseData, error: errorData } = await options.onFetchError({ data: responseData, error: fetchError, response: response.value })) - data.value = responseData + ({ error: errorData } = await options.onFetchError({ data: responseData, error: fetchError, response: response.value })) error.value = errorData errorEvent.trigger(fetchError)