@tanstack/react-query 5.8.3 → 5.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/codemods/coverage/clover.xml +2 -2
- package/build/codemods/coverage/index.html +1 -1
- package/build/legacy/suspense.cjs +1 -1
- package/build/legacy/suspense.cjs.map +1 -1
- package/build/legacy/suspense.d.cts +1 -1
- package/build/legacy/suspense.d.ts +1 -1
- package/build/legacy/suspense.js +1 -1
- package/build/legacy/suspense.js.map +1 -1
- package/build/legacy/useBaseQuery.cjs +2 -1
- package/build/legacy/useBaseQuery.cjs.map +1 -1
- package/build/legacy/useBaseQuery.js +2 -1
- package/build/legacy/useBaseQuery.js.map +1 -1
- package/build/legacy/useQueries.cjs +9 -2
- package/build/legacy/useQueries.cjs.map +1 -1
- package/build/legacy/useQueries.d.cts +18 -2
- package/build/legacy/useQueries.d.ts +18 -2
- package/build/legacy/useQueries.js +9 -2
- package/build/legacy/useQueries.js.map +1 -1
- package/build/legacy/useSuspenseQueries.cjs.map +1 -1
- package/build/legacy/useSuspenseQueries.js.map +1 -1
- package/build/modern/suspense.cjs +1 -1
- package/build/modern/suspense.cjs.map +1 -1
- package/build/modern/suspense.d.cts +1 -1
- package/build/modern/suspense.d.ts +1 -1
- package/build/modern/suspense.js +1 -1
- package/build/modern/suspense.js.map +1 -1
- package/build/modern/useBaseQuery.cjs +2 -1
- package/build/modern/useBaseQuery.cjs.map +1 -1
- package/build/modern/useBaseQuery.js +2 -1
- package/build/modern/useBaseQuery.js.map +1 -1
- package/build/modern/useQueries.cjs +9 -2
- package/build/modern/useQueries.cjs.map +1 -1
- package/build/modern/useQueries.d.cts +18 -2
- package/build/modern/useQueries.d.ts +18 -2
- package/build/modern/useQueries.js +9 -2
- package/build/modern/useQueries.js.map +1 -1
- package/build/modern/useSuspenseQueries.cjs.map +1 -1
- package/build/modern/useSuspenseQueries.js.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/ssr.test.tsx +1 -5
- package/src/__tests__/suspense.test.tsx +146 -0
- package/src/__tests__/useInfiniteQuery.test.tsx +4 -4
- package/src/__tests__/useQuery.test.tsx +0 -9
- package/src/suspense.ts +1 -2
- package/src/useBaseQuery.ts +5 -1
- package/src/useQueries.ts +133 -100
- package/src/useSuspenseQueries.ts +119 -104
|
@@ -887,4 +887,150 @@ describe('useSuspenseQueries', () => {
|
|
|
887
887
|
await waitFor(() => rendered.getByText('data: 1,2'))
|
|
888
888
|
expect(refs[0]).toBe(refs[1])
|
|
889
889
|
})
|
|
890
|
+
|
|
891
|
+
// this addresses the following issue:
|
|
892
|
+
// https://github.com/TanStack/query/issues/6344
|
|
893
|
+
it('should suspend on offline when query changes, and data should not be undefined', async () => {
|
|
894
|
+
function Page() {
|
|
895
|
+
const [id, setId] = React.useState(0)
|
|
896
|
+
|
|
897
|
+
const { data } = useSuspenseQuery({
|
|
898
|
+
queryKey: [id],
|
|
899
|
+
queryFn: () => Promise.resolve(`Data ${id}`),
|
|
900
|
+
})
|
|
901
|
+
|
|
902
|
+
// defensive guard here
|
|
903
|
+
if (data === undefined) {
|
|
904
|
+
throw new Error('data cannot be undefined')
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
return (
|
|
908
|
+
<>
|
|
909
|
+
<div>{data}</div>
|
|
910
|
+
<button onClick={() => setId(id + 1)}>fetch</button>
|
|
911
|
+
</>
|
|
912
|
+
)
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
const rendered = renderWithClient(
|
|
916
|
+
queryClient,
|
|
917
|
+
<React.Suspense fallback={<div>loading</div>}>
|
|
918
|
+
<Page />
|
|
919
|
+
</React.Suspense>,
|
|
920
|
+
)
|
|
921
|
+
|
|
922
|
+
await waitFor(() => rendered.getByText('loading'))
|
|
923
|
+
await waitFor(() => rendered.getByText('Data 0'))
|
|
924
|
+
|
|
925
|
+
// go offline
|
|
926
|
+
document.dispatchEvent(new CustomEvent('offline'))
|
|
927
|
+
|
|
928
|
+
fireEvent.click(rendered.getByText('fetch'))
|
|
929
|
+
await waitFor(() => rendered.getByText('Data 0'))
|
|
930
|
+
|
|
931
|
+
// go back online
|
|
932
|
+
document.dispatchEvent(new CustomEvent('online'))
|
|
933
|
+
fireEvent.click(rendered.getByText('fetch'))
|
|
934
|
+
|
|
935
|
+
// query should resume
|
|
936
|
+
await waitFor(() => rendered.getByText('Data 1'))
|
|
937
|
+
})
|
|
938
|
+
|
|
939
|
+
it('should throw error when queryKey changes and new query fails', async () => {
|
|
940
|
+
const consoleMock = vi
|
|
941
|
+
.spyOn(console, 'error')
|
|
942
|
+
.mockImplementation(() => undefined)
|
|
943
|
+
const key = queryKey()
|
|
944
|
+
|
|
945
|
+
function Page() {
|
|
946
|
+
const [fail, setFail] = React.useState(false)
|
|
947
|
+
const { data } = useSuspenseQuery({
|
|
948
|
+
queryKey: [key, fail],
|
|
949
|
+
queryFn: async () => {
|
|
950
|
+
await sleep(10)
|
|
951
|
+
|
|
952
|
+
if (fail) {
|
|
953
|
+
throw new Error('Suspense Error Bingo')
|
|
954
|
+
} else {
|
|
955
|
+
return 'data'
|
|
956
|
+
}
|
|
957
|
+
},
|
|
958
|
+
retry: 0,
|
|
959
|
+
})
|
|
960
|
+
|
|
961
|
+
return (
|
|
962
|
+
<div>
|
|
963
|
+
<button onClick={() => setFail(true)}>trigger fail</button>
|
|
964
|
+
|
|
965
|
+
<div>rendered: {String(data)}</div>
|
|
966
|
+
</div>
|
|
967
|
+
)
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
const rendered = renderWithClient(
|
|
971
|
+
queryClient,
|
|
972
|
+
<ErrorBoundary fallbackRender={() => <div>error boundary</div>}>
|
|
973
|
+
<React.Suspense fallback={'Loading...'}>
|
|
974
|
+
<Page />
|
|
975
|
+
</React.Suspense>
|
|
976
|
+
</ErrorBoundary>,
|
|
977
|
+
)
|
|
978
|
+
|
|
979
|
+
await waitFor(() => rendered.getByText('Loading...'))
|
|
980
|
+
|
|
981
|
+
await waitFor(() => rendered.getByText('rendered: data'))
|
|
982
|
+
|
|
983
|
+
fireEvent.click(rendered.getByText('trigger fail'))
|
|
984
|
+
|
|
985
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
986
|
+
|
|
987
|
+
expect(consoleMock).toHaveBeenCalledWith(
|
|
988
|
+
expect.objectContaining(new Error('Suspense Error Bingo')),
|
|
989
|
+
)
|
|
990
|
+
|
|
991
|
+
consoleMock.mockRestore()
|
|
992
|
+
})
|
|
993
|
+
|
|
994
|
+
it('should keep previous data when wrapped in a transition', async () => {
|
|
995
|
+
const key = queryKey()
|
|
996
|
+
|
|
997
|
+
function Page() {
|
|
998
|
+
const [count, setCount] = React.useState(0)
|
|
999
|
+
const [isPending, startTransition] = React.useTransition()
|
|
1000
|
+
const { data } = useSuspenseQuery({
|
|
1001
|
+
queryKey: [key, count],
|
|
1002
|
+
queryFn: async () => {
|
|
1003
|
+
await sleep(10)
|
|
1004
|
+
return 'data' + count
|
|
1005
|
+
},
|
|
1006
|
+
})
|
|
1007
|
+
|
|
1008
|
+
return (
|
|
1009
|
+
<div>
|
|
1010
|
+
<button onClick={() => startTransition(() => setCount(count + 1))}>
|
|
1011
|
+
inc
|
|
1012
|
+
</button>
|
|
1013
|
+
|
|
1014
|
+
<div>{isPending ? 'Pending...' : String(data)}</div>
|
|
1015
|
+
</div>
|
|
1016
|
+
)
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
const rendered = renderWithClient(
|
|
1020
|
+
queryClient,
|
|
1021
|
+
<React.Suspense fallback={'Loading...'}>
|
|
1022
|
+
<Page />
|
|
1023
|
+
</React.Suspense>,
|
|
1024
|
+
)
|
|
1025
|
+
|
|
1026
|
+
await waitFor(() => rendered.getByText('Loading...'))
|
|
1027
|
+
|
|
1028
|
+
await waitFor(() => rendered.getByText('data0'))
|
|
1029
|
+
|
|
1030
|
+
fireEvent.click(rendered.getByText('inc'))
|
|
1031
|
+
|
|
1032
|
+
await waitFor(() => rendered.getByText('Pending...'))
|
|
1033
|
+
|
|
1034
|
+
await waitFor(() => rendered.getByText('data1'))
|
|
1035
|
+
})
|
|
890
1036
|
})
|
|
@@ -1253,8 +1253,8 @@ describe('useInfiniteQuery', () => {
|
|
|
1253
1253
|
{isFetchingNextPage
|
|
1254
1254
|
? 'Loading more...'
|
|
1255
1255
|
: hasNextPage
|
|
1256
|
-
|
|
1257
|
-
|
|
1256
|
+
? 'Load More'
|
|
1257
|
+
: 'Nothing more to load'}
|
|
1258
1258
|
</button>
|
|
1259
1259
|
<button onClick={() => refetch()}>Refetch</button>
|
|
1260
1260
|
<button
|
|
@@ -1382,8 +1382,8 @@ describe('useInfiniteQuery', () => {
|
|
|
1382
1382
|
{isFetchingNextPage
|
|
1383
1383
|
? 'Loading more...'
|
|
1384
1384
|
: hasNextPage
|
|
1385
|
-
|
|
1386
|
-
|
|
1385
|
+
? 'Load More'
|
|
1386
|
+
: 'Nothing more to load'}
|
|
1387
1387
|
</button>
|
|
1388
1388
|
<button onClick={() => refetch()}>Refetch</button>
|
|
1389
1389
|
<button onClick={() => setIsRemovedLastPage(true)}>
|
|
@@ -1108,7 +1108,6 @@ describe('useQuery', () => {
|
|
|
1108
1108
|
|
|
1109
1109
|
it('should use query function from hook when the existing query does not have a query function', async () => {
|
|
1110
1110
|
const key = queryKey()
|
|
1111
|
-
const results: Array<DefinedUseQueryResult<string>> = []
|
|
1112
1111
|
|
|
1113
1112
|
queryClient.setQueryData(key, 'set')
|
|
1114
1113
|
|
|
@@ -1124,8 +1123,6 @@ describe('useQuery', () => {
|
|
|
1124
1123
|
staleTime: Infinity,
|
|
1125
1124
|
})
|
|
1126
1125
|
|
|
1127
|
-
results.push(result)
|
|
1128
|
-
|
|
1129
1126
|
return (
|
|
1130
1127
|
<div>
|
|
1131
1128
|
<div>isFetching: {result.isFetching}</div>
|
|
@@ -1142,12 +1139,6 @@ describe('useQuery', () => {
|
|
|
1142
1139
|
await waitFor(() => rendered.getByText('data: set'))
|
|
1143
1140
|
fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))
|
|
1144
1141
|
await waitFor(() => rendered.getByText('data: fetched'))
|
|
1145
|
-
|
|
1146
|
-
await waitFor(() => expect(results.length).toBe(3))
|
|
1147
|
-
|
|
1148
|
-
expect(results[0]).toMatchObject({ data: 'set', isFetching: false })
|
|
1149
|
-
expect(results[1]).toMatchObject({ data: 'set', isFetching: true })
|
|
1150
|
-
expect(results[2]).toMatchObject({ data: 'fetched', isFetching: false })
|
|
1151
1142
|
})
|
|
1152
1143
|
|
|
1153
1144
|
it('should update query stale state and refetch when invalidated with invalidateQueries', async () => {
|
package/src/suspense.ts
CHANGED
|
@@ -40,8 +40,7 @@ export const shouldSuspend = (
|
|
|
40
40
|
| DefaultedQueryObserverOptions<any, any, any, any, any>
|
|
41
41
|
| undefined,
|
|
42
42
|
result: QueryObserverResult<any, any>,
|
|
43
|
-
|
|
44
|
-
) => defaultedOptions?.suspense && willFetch(result, isRestoring)
|
|
43
|
+
) => defaultedOptions?.suspense && result.isPending
|
|
45
44
|
|
|
46
45
|
export const fetchOptimistic = <
|
|
47
46
|
TQueryFnData,
|
package/src/useBaseQuery.ts
CHANGED
|
@@ -90,7 +90,11 @@ export function useBaseQuery<
|
|
|
90
90
|
}, [defaultedOptions, observer])
|
|
91
91
|
|
|
92
92
|
// Handle suspense
|
|
93
|
-
if (shouldSuspend(defaultedOptions, result
|
|
93
|
+
if (shouldSuspend(defaultedOptions, result)) {
|
|
94
|
+
// Do the same thing as the effect right above because the effect won't run
|
|
95
|
+
// when we suspend but also, the component won't re-mount so our observer would
|
|
96
|
+
// be out of date.
|
|
97
|
+
observer.setOptions(defaultedOptions, { listeners: false })
|
|
94
98
|
throw fetchOptimistic(defaultedOptions, observer, errorResetBoundary)
|
|
95
99
|
}
|
|
96
100
|
|
package/src/useQueries.ts
CHANGED
|
@@ -57,68 +57,79 @@ type GetOptions<T> =
|
|
|
57
57
|
}
|
|
58
58
|
? UseQueryOptionsForUseQueries<TQueryFnData, TError, TData>
|
|
59
59
|
: T extends { queryFnData: infer TQueryFnData; error?: infer TError }
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
60
|
+
? UseQueryOptionsForUseQueries<TQueryFnData, TError>
|
|
61
|
+
: T extends { data: infer TData; error?: infer TError }
|
|
62
|
+
? UseQueryOptionsForUseQueries<unknown, TError, TData>
|
|
63
|
+
: // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]
|
|
64
|
+
T extends [infer TQueryFnData, infer TError, infer TData]
|
|
65
|
+
? UseQueryOptionsForUseQueries<TQueryFnData, TError, TData>
|
|
66
|
+
: T extends [infer TQueryFnData, infer TError]
|
|
67
|
+
? UseQueryOptionsForUseQueries<TQueryFnData, TError>
|
|
68
|
+
: T extends [infer TQueryFnData]
|
|
69
|
+
? UseQueryOptionsForUseQueries<TQueryFnData>
|
|
70
|
+
: // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided
|
|
71
|
+
T extends {
|
|
72
|
+
queryFn?: QueryFunction<infer TQueryFnData, infer TQueryKey>
|
|
73
|
+
select: (data: any) => infer TData
|
|
74
|
+
throwOnError?: ThrowOnError<any, infer TError, any, any>
|
|
75
|
+
}
|
|
76
|
+
? UseQueryOptionsForUseQueries<
|
|
77
|
+
TQueryFnData,
|
|
78
|
+
TError,
|
|
79
|
+
TData,
|
|
80
|
+
TQueryKey
|
|
81
|
+
>
|
|
82
|
+
: T extends {
|
|
83
|
+
queryFn?: QueryFunction<
|
|
84
|
+
infer TQueryFnData,
|
|
85
|
+
infer TQueryKey
|
|
86
|
+
>
|
|
87
|
+
throwOnError?: ThrowOnError<any, infer TError, any, any>
|
|
88
|
+
}
|
|
89
|
+
? UseQueryOptionsForUseQueries<
|
|
90
|
+
TQueryFnData,
|
|
91
|
+
TError,
|
|
92
|
+
TQueryFnData,
|
|
93
|
+
TQueryKey
|
|
94
|
+
>
|
|
95
|
+
: // Fallback
|
|
96
|
+
UseQueryOptionsForUseQueries
|
|
89
97
|
|
|
90
98
|
type GetResults<T> =
|
|
91
99
|
// Part 1: responsible for mapping explicit type parameter to function result, if object
|
|
92
100
|
T extends { queryFnData: any; error?: infer TError; data: infer TData }
|
|
93
101
|
? UseQueryResult<TData, TError>
|
|
94
102
|
: T extends { queryFnData: infer TQueryFnData; error?: infer TError }
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
103
|
+
? UseQueryResult<TQueryFnData, TError>
|
|
104
|
+
: T extends { data: infer TData; error?: infer TError }
|
|
105
|
+
? UseQueryResult<TData, TError>
|
|
106
|
+
: // Part 2: responsible for mapping explicit type parameter to function result, if tuple
|
|
107
|
+
T extends [any, infer TError, infer TData]
|
|
108
|
+
? UseQueryResult<TData, TError>
|
|
109
|
+
: T extends [infer TQueryFnData, infer TError]
|
|
110
|
+
? UseQueryResult<TQueryFnData, TError>
|
|
111
|
+
: T extends [infer TQueryFnData]
|
|
112
|
+
? UseQueryResult<TQueryFnData>
|
|
113
|
+
: // Part 3: responsible for mapping inferred type to results, if no explicit parameter was provided
|
|
114
|
+
T extends {
|
|
115
|
+
queryFn?: QueryFunction<unknown, any>
|
|
116
|
+
select: (data: any) => infer TData
|
|
117
|
+
throwOnError?: ThrowOnError<any, infer TError, any, any>
|
|
118
|
+
}
|
|
119
|
+
? UseQueryResult<
|
|
120
|
+
TData,
|
|
121
|
+
unknown extends TError ? DefaultError : TError
|
|
122
|
+
>
|
|
123
|
+
: T extends {
|
|
124
|
+
queryFn?: QueryFunction<infer TQueryFnData, any>
|
|
125
|
+
throwOnError?: ThrowOnError<any, infer TError, any, any>
|
|
126
|
+
}
|
|
127
|
+
? UseQueryResult<
|
|
128
|
+
TQueryFnData,
|
|
129
|
+
unknown extends TError ? DefaultError : TError
|
|
130
|
+
>
|
|
131
|
+
: // Fallback
|
|
132
|
+
UseQueryResult
|
|
122
133
|
|
|
123
134
|
/**
|
|
124
135
|
* QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param
|
|
@@ -130,26 +141,37 @@ export type QueriesOptions<
|
|
|
130
141
|
> = Depth['length'] extends MAXIMUM_DEPTH
|
|
131
142
|
? Array<UseQueryOptionsForUseQueries>
|
|
132
143
|
: T extends []
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
144
|
+
? []
|
|
145
|
+
: T extends [infer Head]
|
|
146
|
+
? [...Result, GetOptions<Head>]
|
|
147
|
+
: T extends [infer Head, ...infer Tail]
|
|
148
|
+
? QueriesOptions<
|
|
149
|
+
[...Tail],
|
|
150
|
+
[...Result, GetOptions<Head>],
|
|
151
|
+
[...Depth, 1]
|
|
152
|
+
>
|
|
153
|
+
: Array<unknown> extends T
|
|
154
|
+
? T
|
|
155
|
+
: // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!
|
|
156
|
+
// use this to infer the param types in the case of Array.map() argument
|
|
157
|
+
T extends Array<
|
|
158
|
+
UseQueryOptionsForUseQueries<
|
|
159
|
+
infer TQueryFnData,
|
|
160
|
+
infer TError,
|
|
161
|
+
infer TData,
|
|
162
|
+
infer TQueryKey
|
|
163
|
+
>
|
|
164
|
+
>
|
|
165
|
+
? Array<
|
|
166
|
+
UseQueryOptionsForUseQueries<
|
|
167
|
+
TQueryFnData,
|
|
168
|
+
TError,
|
|
169
|
+
TData,
|
|
170
|
+
TQueryKey
|
|
171
|
+
>
|
|
172
|
+
>
|
|
173
|
+
: // Fallback
|
|
174
|
+
Array<UseQueryOptionsForUseQueries>
|
|
153
175
|
|
|
154
176
|
/**
|
|
155
177
|
* QueriesResults reducer recursively maps type param to results
|
|
@@ -161,28 +183,32 @@ export type QueriesResults<
|
|
|
161
183
|
> = Depth['length'] extends MAXIMUM_DEPTH
|
|
162
184
|
? Array<UseQueryResult>
|
|
163
185
|
: T extends []
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
+
? []
|
|
187
|
+
: T extends [infer Head]
|
|
188
|
+
? [...Result, GetResults<Head>]
|
|
189
|
+
: T extends [infer Head, ...infer Tail]
|
|
190
|
+
? QueriesResults<
|
|
191
|
+
[...Tail],
|
|
192
|
+
[...Result, GetResults<Head>],
|
|
193
|
+
[...Depth, 1]
|
|
194
|
+
>
|
|
195
|
+
: T extends Array<
|
|
196
|
+
UseQueryOptionsForUseQueries<
|
|
197
|
+
infer TQueryFnData,
|
|
198
|
+
infer TError,
|
|
199
|
+
infer TData,
|
|
200
|
+
any
|
|
201
|
+
>
|
|
202
|
+
>
|
|
203
|
+
? // Dynamic-size (homogenous) UseQueryOptions array: map directly to array of results
|
|
204
|
+
Array<
|
|
205
|
+
UseQueryResult<
|
|
206
|
+
unknown extends TData ? TQueryFnData : TData,
|
|
207
|
+
unknown extends TError ? DefaultError : TError
|
|
208
|
+
>
|
|
209
|
+
>
|
|
210
|
+
: // Fallback
|
|
211
|
+
Array<UseQueryResult>
|
|
186
212
|
|
|
187
213
|
export function useQueries<
|
|
188
214
|
T extends Array<any>,
|
|
@@ -260,7 +286,7 @@ export function useQueries<
|
|
|
260
286
|
}, [defaultedQueries, options, observer])
|
|
261
287
|
|
|
262
288
|
const shouldAtLeastOneSuspend = optimisticResult.some((result, index) =>
|
|
263
|
-
shouldSuspend(defaultedQueries[index], result
|
|
289
|
+
shouldSuspend(defaultedQueries[index], result),
|
|
264
290
|
)
|
|
265
291
|
|
|
266
292
|
const suspensePromises = shouldAtLeastOneSuspend
|
|
@@ -269,7 +295,7 @@ export function useQueries<
|
|
|
269
295
|
|
|
270
296
|
if (opts) {
|
|
271
297
|
const queryObserver = new QueryObserver(client, opts)
|
|
272
|
-
if (shouldSuspend(opts, result
|
|
298
|
+
if (shouldSuspend(opts, result)) {
|
|
273
299
|
return fetchOptimistic(opts, queryObserver, errorResetBoundary)
|
|
274
300
|
} else if (willFetch(result, isRestoring)) {
|
|
275
301
|
void fetchOptimistic(opts, queryObserver, errorResetBoundary)
|
|
@@ -280,6 +306,13 @@ export function useQueries<
|
|
|
280
306
|
: []
|
|
281
307
|
|
|
282
308
|
if (suspensePromises.length > 0) {
|
|
309
|
+
observer.setQueries(
|
|
310
|
+
defaultedQueries,
|
|
311
|
+
options as QueriesObserverOptions<TCombinedResult>,
|
|
312
|
+
{
|
|
313
|
+
listeners: false,
|
|
314
|
+
},
|
|
315
|
+
)
|
|
283
316
|
throw Promise.all(suspensePromises)
|
|
284
317
|
}
|
|
285
318
|
const observerQueries = observer.getQueries()
|