From 8cbd6a05a90c8b3c6c3cc0e4143162111ff195cd Mon Sep 17 00:00:00 2001 From: KATT Date: Sun, 1 Sep 2024 21:31:11 +0200 Subject: [PATCH] =?UTF-8?q?let=E2=80=99s=20do=20it=20again?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/query-core/src/queryObserver.ts | 5 ++ packages/query-core/src/types.ts | 4 + packages/react-query/package.json | 2 +- .../src/__tests__/useQuery.test.tsx | 74 +++++++++++++++++++ 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/packages/query-core/src/queryObserver.ts b/packages/query-core/src/queryObserver.ts index 2971bc6d1a..64c5420ade 100644 --- a/packages/query-core/src/queryObserver.ts +++ b/packages/query-core/src/queryObserver.ts @@ -582,6 +582,11 @@ export class QueryObserver< isRefetchError: isError && hasData, isStale: isStale(query, options), refetch: this.refetch, + promise: (prevQuery.promise ?? + query.promise ?? + new Promise(() => { + // never resolves? 🤷‍♂️ + })) as any, } return result as QueryObserverResult diff --git a/packages/query-core/src/types.ts b/packages/query-core/src/types.ts index 140cb1f867..75ffc90be9 100644 --- a/packages/query-core/src/types.ts +++ b/packages/query-core/src/types.ts @@ -661,6 +661,10 @@ export interface QueryObserverBaseResult< * - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. */ fetchStatus: FetchStatus + /** + * A stable promise that will be resolved with the data of the query. + */ + promise: Promise } export interface QueryObserverPendingResult< diff --git a/packages/react-query/package.json b/packages/react-query/package.json index c774706789..4ee68dc079 100644 --- a/packages/react-query/package.json +++ b/packages/react-query/package.json @@ -25,7 +25,7 @@ "test:types:ts51": "node ../../node_modules/typescript51/lib/tsc.js -p tsconfig.legacy.json", "test:types:ts52": "node ../../node_modules/typescript52/lib/tsc.js -p tsconfig.legacy.json", "test:types:ts53": "tsc", - "test:lib": "vitest --retry=3", + "test:lib": "vitest", "test:lib:dev": "pnpm run test:lib --watch", "test:build": "publint --strict && attw --pack", "build": "pnpm build:tsup && pnpm build:codemods", diff --git a/packages/react-query/src/__tests__/useQuery.test.tsx b/packages/react-query/src/__tests__/useQuery.test.tsx index fad1aee708..e49962511d 100644 --- a/packages/react-query/src/__tests__/useQuery.test.tsx +++ b/packages/react-query/src/__tests__/useQuery.test.tsx @@ -41,6 +41,7 @@ describe('useQuery', () => { const fromQueryFn = useQuery({ queryKey: key, queryFn: () => 'test' }) expectTypeOf(fromQueryFn.data).toEqualTypeOf() expectTypeOf(fromQueryFn.error).toEqualTypeOf() + expectTypeOf(fromQueryFn.promise).toEqualTypeOf>() // it should be possible to specify the result type const withResult = useQuery({ @@ -6581,4 +6582,77 @@ describe('useQuery', () => { consoleMock.mockRestore() }) + + describe('useQuery().promise', () => { + it('should work with a basic test', async () => { + const key = queryKey() + let suspenseRenderCount = 0 + + function MyComponent(props: { promise: Promise }) { + return
{React.use(props.promise)}
+ } + + function Loading() { + suspenseRenderCount++ + return <>loading.. + } + function Page() { + const query = useQuery({ + queryKey: key, + queryFn: async () => { + await sleep(10) + return 'test' + }, + }) + + return ( + }> + + + ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('loading..')) + await waitFor(() => rendered.getByText('test')) + + // This should probably be 1 since `.promise` is the only "watched" property + // expect(suspenseRenderCount).toBe(1) + }) + }) + + it('should work with initial data', async () => { + const key = queryKey() + let suspenseRenderCount = 0 + + function MyComponent(props: { promise: Promise }) { + return
{React.use(props.promise)}
+ } + function Loading() { + suspenseRenderCount++ + return <>loading.. + } + function Page() { + const query = useQuery({ + queryKey: key, + queryFn: async () => { + await sleep(10) + return 'test' + }, + initialData: 'initial', + }) + + return ( + }> + + + ) + } + + const rendered = renderWithClient(queryClient, ) + await waitFor(() => rendered.getByText('initialData')) + await waitFor(() => rendered.getByText('test')) + + expect(suspenseRenderCount).toBe(0) + }) })