@tanstack/solid-query 5.102.8 → 5.103.0
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/dev.cjs +407 -0
- package/build/dev.js +407 -0
- package/build/index.d.cts +1194 -1
- package/build/index.d.cts.map +1 -1
- package/build/index.d.ts +1194 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js.map +1 -1
- package/package.json +10 -10
- package/src/QueryClient.ts +33 -0
- package/src/QueryClientProvider.tsx +41 -0
- package/src/infiniteQueryOptions.ts +111 -0
- package/src/isRestoring.ts +12 -0
- package/src/mutationOptions.ts +55 -0
- package/src/queryOptions.ts +98 -4
- package/src/types.ts +139 -0
- package/src/useInfiniteQuery.ts +151 -0
- package/src/useIsFetching.ts +22 -0
- package/src/useIsMutating.ts +21 -0
- package/src/useMutation.ts +159 -1
- package/src/useMutationState.ts +73 -0
- package/src/useQueries.ts +87 -0
- package/src/useQuery.ts +199 -0
package/build/index.d.ts
CHANGED
|
@@ -2,6 +2,17 @@ import { DefaultError, DefaultOptions as DefaultOptions$1, DefinedInfiniteQueryO
|
|
|
2
2
|
import { Accessor, JSX } from "solid-js";
|
|
3
3
|
export * from "@tanstack/query-core";
|
|
4
4
|
//#region src/QueryClient.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* The core `QueryObserverOptions`, with Solid's `reconcile` option added.
|
|
7
|
+
*
|
|
8
|
+
* @template TQueryFnData - The type your `queryFn` resolves to.
|
|
9
|
+
* @template TError - The type of errors your `queryFn` may throw.
|
|
10
|
+
* @template TData - The type `data` ends up as after `select` runs.
|
|
11
|
+
* @template TQueryData - The type of the data actually held in the query cache.
|
|
12
|
+
* @template TQueryKey - The type of your `queryKey`.
|
|
13
|
+
* @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page, when this type
|
|
14
|
+
* is shared with an infinite query's observer options. Defaults to `never` for regular queries.
|
|
15
|
+
*/
|
|
5
16
|
interface QueryObserverOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, TPageParam = never> extends OmitKeyof<QueryObserverOptions$1<TQueryFnData, TError, TData, TQueryData, TQueryKey, TPageParam>, 'structuralSharing'> {
|
|
6
17
|
/**
|
|
7
18
|
* Set this to a reconciliation key to enable reconciliation between query results.
|
|
@@ -11,6 +22,15 @@ interface QueryObserverOptions<TQueryFnData = unknown, TError = DefaultError, TD
|
|
|
11
22
|
*/
|
|
12
23
|
reconcile?: string | false | ((oldData: TData | undefined, newData: TData) => TData);
|
|
13
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* The core `InfiniteQueryObserverOptions`, with Solid's `reconcile` option added.
|
|
27
|
+
*
|
|
28
|
+
* @template TQueryFnData - The type of a single page, as your `queryFn` resolves it.
|
|
29
|
+
* @template TError - The type of errors your `queryFn` may throw.
|
|
30
|
+
* @template TData - The type `data` ends up as after `select` runs.
|
|
31
|
+
* @template TQueryKey - The type of your `queryKey`.
|
|
32
|
+
* @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page.
|
|
33
|
+
*/
|
|
14
34
|
interface InfiniteQueryObserverOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, TPageParam = unknown> extends OmitKeyof<InfiniteQueryObserverOptions$1<TQueryFnData, TError, TData, TQueryKey, TPageParam>, 'structuralSharing'> {
|
|
15
35
|
/**
|
|
16
36
|
* Set this to a reconciliation key to enable reconciliation between query results.
|
|
@@ -20,17 +40,42 @@ interface InfiniteQueryObserverOptions<TQueryFnData = unknown, TError = DefaultE
|
|
|
20
40
|
*/
|
|
21
41
|
reconcile?: string | false | ((oldData: TData | undefined, newData: TData) => TData);
|
|
22
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* The default options a `QueryClient` applies to every query, with Solid's `reconcile` option added to
|
|
45
|
+
* `queries`.
|
|
46
|
+
*
|
|
47
|
+
* @template TError - The default type of errors thrown by queries and mutations using this `QueryClient`.
|
|
48
|
+
*/
|
|
23
49
|
interface DefaultOptions<TError = DefaultError> extends DefaultOptions$1<TError> {
|
|
24
50
|
queries?: OmitKeyof<QueryObserverOptions<unknown, TError>, 'queryKey'>;
|
|
25
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* The config accepted by `new QueryClient(config)`, with Solid's extended {@link DefaultOptions}.
|
|
54
|
+
*/
|
|
26
55
|
interface QueryClientConfig extends QueryClientConfig$1 {
|
|
27
56
|
defaultOptions?: DefaultOptions;
|
|
28
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* The core `@tanstack/query-core` `QueryClient`, typed so its `defaultOptions.queries` accepts Solid's
|
|
60
|
+
* `reconcile` option.
|
|
61
|
+
*/
|
|
29
62
|
declare class QueryClient extends QueryClient$1 {
|
|
30
63
|
constructor(config?: QueryClientConfig);
|
|
31
64
|
}
|
|
32
65
|
//#endregion
|
|
33
66
|
//#region src/types.d.ts
|
|
67
|
+
/**
|
|
68
|
+
* The options accepted by `useQuery`. Extends {@link QueryObserverOptions} from `@tanstack/query-core` with
|
|
69
|
+
* the `solid-query`-specific `deferStream` and `suspense` options.
|
|
70
|
+
*
|
|
71
|
+
* @template TQueryFnData - The type your `queryFn` resolves to.
|
|
72
|
+
* @template TError - The type of errors your `queryFn` may throw.
|
|
73
|
+
* @template TData - The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` when no
|
|
74
|
+
* `select` is used.
|
|
75
|
+
* @template TQueryData - The type of the data actually held in the query cache — the input to `select` and
|
|
76
|
+
* `placeholderData`. Defaults to, and is usually the same as, `TQueryFnData`.
|
|
77
|
+
* @template TQueryKey - The type of your `queryKey`.
|
|
78
|
+
*/
|
|
34
79
|
interface UseBaseQueryOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryData = TQueryFnData, TQueryKey extends QueryKey = QueryKey> extends OmitKeyof<QueryObserverOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>, 'suspense'> {
|
|
35
80
|
/**
|
|
36
81
|
* Only applicable while rendering queries on the server with streaming.
|
|
@@ -46,12 +91,67 @@ interface UseBaseQueryOptions<TQueryFnData = unknown, TError = DefaultError, TDa
|
|
|
46
91
|
*/
|
|
47
92
|
suspense?: boolean;
|
|
48
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* The options accepted by `useQuery` and `queryOptions`.
|
|
96
|
+
*
|
|
97
|
+
* @template TQueryFnData - The type your `queryFn` resolves to.
|
|
98
|
+
* @template TError - The type of errors your `queryFn` may throw.
|
|
99
|
+
* @template TData - The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` when no
|
|
100
|
+
* `select` is used.
|
|
101
|
+
* @template TQueryKey - The type of your `queryKey`.
|
|
102
|
+
*/
|
|
49
103
|
interface QueryOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey> extends UseBaseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey> {}
|
|
104
|
+
/**
|
|
105
|
+
* The accessor `useQuery` expects as its first argument — Solid re-evaluates it reactively, so `queryKey` and
|
|
106
|
+
* other options can depend on signals.
|
|
107
|
+
*
|
|
108
|
+
* @template TQueryFnData - The type your `queryFn` resolves to.
|
|
109
|
+
* @template TError - The type of errors your `queryFn` may throw.
|
|
110
|
+
* @template TData - The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` when no
|
|
111
|
+
* `select` is used.
|
|
112
|
+
* @template TQueryKey - The type of your `queryKey`.
|
|
113
|
+
*/
|
|
50
114
|
type UseQueryOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey> = Accessor<QueryOptions<TQueryFnData, TError, TData, TQueryKey>>;
|
|
115
|
+
/**
|
|
116
|
+
* The object `useQuery` returns when `initialData` isn't set — `data`/`error` may still be `undefined`/`null`
|
|
117
|
+
* while the query is `pending`. Re-exports {@link QueryObserverResult} from `@tanstack/query-core`.
|
|
118
|
+
* `useInfiniteQuery` returns {@link UseInfiniteQueryResult} instead.
|
|
119
|
+
*
|
|
120
|
+
* @template TData - The type `data` ends up as, after `select` runs (if set).
|
|
121
|
+
* @template TError - The type of errors this query may hold.
|
|
122
|
+
*/
|
|
51
123
|
type UseBaseQueryResult<TData = unknown, TError = DefaultError> = QueryObserverResult<TData, TError>;
|
|
124
|
+
/**
|
|
125
|
+
* The object `useQuery` returns — `data`/`error` may still be `undefined`/`null` while the query is
|
|
126
|
+
* `pending`.
|
|
127
|
+
*
|
|
128
|
+
* @template TData - The type `data` ends up as, after `select` runs (if set).
|
|
129
|
+
* @template TError - The type of errors this query may hold.
|
|
130
|
+
*/
|
|
52
131
|
type UseQueryResult<TData = unknown, TError = DefaultError> = UseBaseQueryResult<TData, TError>;
|
|
132
|
+
/**
|
|
133
|
+
* The object `useQuery` returns when `initialData` guarantees `data` is never `undefined`.
|
|
134
|
+
*
|
|
135
|
+
* @template TData - The type `data` ends up as, after `select` runs (if set).
|
|
136
|
+
* @template TError - The type of errors this query may hold.
|
|
137
|
+
*/
|
|
53
138
|
type DefinedUseBaseQueryResult<TData = unknown, TError = DefaultError> = DefinedQueryObserverResult<TData, TError>;
|
|
139
|
+
/**
|
|
140
|
+
* The object `useQuery` returns when `initialData` guarantees `data` is never `undefined`.
|
|
141
|
+
*
|
|
142
|
+
* @template TData - The type `data` ends up as, after `select` runs (if set).
|
|
143
|
+
* @template TError - The type of errors this query may hold.
|
|
144
|
+
*/
|
|
54
145
|
type DefinedUseQueryResult<TData = unknown, TError = DefaultError> = DefinedUseBaseQueryResult<TData, TError>;
|
|
146
|
+
/**
|
|
147
|
+
* The options accepted by `useInfiniteQuery`.
|
|
148
|
+
*
|
|
149
|
+
* @template TQueryFnData - The type of a single page, as your `queryFn` resolves it.
|
|
150
|
+
* @template TError - The type of errors your `queryFn` may throw.
|
|
151
|
+
* @template TData - The type `data` ends up as after `select` runs.
|
|
152
|
+
* @template TQueryKey - The type of your `queryKey`.
|
|
153
|
+
* @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page.
|
|
154
|
+
*/
|
|
55
155
|
interface InfiniteQueryOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, TPageParam = unknown> extends OmitKeyof<InfiniteQueryObserverOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>, 'queryKey' | 'suspense'> {
|
|
56
156
|
queryKey: TQueryKey;
|
|
57
157
|
/**
|
|
@@ -68,49 +168,832 @@ interface InfiniteQueryOptions<TQueryFnData = unknown, TError = DefaultError, TD
|
|
|
68
168
|
*/
|
|
69
169
|
suspense?: boolean;
|
|
70
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* The accessor `useInfiniteQuery` expects as its first argument — Solid re-evaluates it reactively, so
|
|
173
|
+
* `queryKey` and other options can depend on signals.
|
|
174
|
+
*
|
|
175
|
+
* @template TQueryFnData - The type of a single page, as your `queryFn` resolves it.
|
|
176
|
+
* @template TError - The type of errors your `queryFn` may throw.
|
|
177
|
+
* @template TData - The type `data` ends up as after `select` runs.
|
|
178
|
+
* @template TQueryKey - The type of your `queryKey`.
|
|
179
|
+
* @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page.
|
|
180
|
+
*/
|
|
71
181
|
type UseInfiniteQueryOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, TPageParam = unknown> = Accessor<InfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>>;
|
|
182
|
+
/**
|
|
183
|
+
* The object `useInfiniteQuery` returns — `data`/`error` may still be `undefined`/`null` while the query is
|
|
184
|
+
* `pending`.
|
|
185
|
+
*
|
|
186
|
+
* @template TData - The type `data` ends up as, after `select` runs (if set).
|
|
187
|
+
* @template TError - The type of errors this query may hold.
|
|
188
|
+
*/
|
|
72
189
|
type UseInfiniteQueryResult<TData = unknown, TError = DefaultError> = InfiniteQueryObserverResult<TData, TError>;
|
|
190
|
+
/**
|
|
191
|
+
* The object `useInfiniteQuery` returns when `initialData` guarantees `data` is never `undefined`.
|
|
192
|
+
*
|
|
193
|
+
* @template TData - The type `data` ends up as, after `select` runs (if set).
|
|
194
|
+
* @template TError - The type of errors this query may hold.
|
|
195
|
+
*/
|
|
73
196
|
type DefinedUseInfiniteQueryResult<TData = unknown, TError = DefaultError> = DefinedInfiniteQueryObserverResult<TData, TError>;
|
|
197
|
+
/**
|
|
198
|
+
* The options accepted by `useMutation` and `mutationOptions`.
|
|
199
|
+
*
|
|
200
|
+
* @template TData - The type your `mutationFn` resolves to.
|
|
201
|
+
* @template TError - The type of errors your `mutationFn` may throw.
|
|
202
|
+
* @template TVariables - The type of the variables your `mutationFn` accepts.
|
|
203
|
+
* @template TOnMutateResult - The type returned by `onMutate`, passed on to `onSuccess`/`onError`/`onSettled`.
|
|
204
|
+
*/
|
|
74
205
|
interface MutationOptions<TData = unknown, TError = DefaultError, TVariables = void, TOnMutateResult = unknown> extends OmitKeyof<MutationObserverOptions<TData, TError, TVariables, TOnMutateResult>, '_defaulted'> {}
|
|
206
|
+
/**
|
|
207
|
+
* The accessor `useMutation` expects as its first argument — Solid re-evaluates it reactively, so callbacks
|
|
208
|
+
* and other options can depend on signals.
|
|
209
|
+
*
|
|
210
|
+
* @template TData - The type your `mutationFn` resolves to.
|
|
211
|
+
* @template TError - The type of errors your `mutationFn` may throw.
|
|
212
|
+
* @template TVariables - The type of the variables your `mutationFn` accepts.
|
|
213
|
+
* @template TOnMutateResult - The type returned by `onMutate`, passed on to `onSuccess`/`onError`/`onSettled`.
|
|
214
|
+
*/
|
|
75
215
|
type UseMutationOptions<TData = unknown, TError = DefaultError, TVariables = void, TOnMutateResult = unknown> = Accessor<MutationOptions<TData, TError, TVariables, TOnMutateResult>>;
|
|
76
216
|
type UseMutateFunction<TData = unknown, TError = DefaultError, TVariables = void, TOnMutateResult = unknown> = (...args: Parameters<MutateFunction<TData, TError, TVariables, TOnMutateResult>>) => void;
|
|
217
|
+
/**
|
|
218
|
+
* The type of `mutateAsync`, as returned by `useMutation`. Similar to {@link UseMutateFunction}, but returns a
|
|
219
|
+
* promise which can be awaited.
|
|
220
|
+
*
|
|
221
|
+
* @template TData - The type your `mutationFn` resolves to.
|
|
222
|
+
* @template TError - The type of errors your `mutationFn` may throw.
|
|
223
|
+
* @template TVariables - The type of the variable passed to `mutateAsync`.
|
|
224
|
+
* @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as
|
|
225
|
+
* their `onMutateResult` parameter — useful for optimistic-update rollback data.
|
|
226
|
+
*/
|
|
77
227
|
type UseMutateAsyncFunction<TData = unknown, TError = DefaultError, TVariables = void, TOnMutateResult = unknown> = MutateFunction<TData, TError, TVariables, TOnMutateResult>;
|
|
228
|
+
/**
|
|
229
|
+
* The result of `useMutation`. Same as {@link MutationObserverResult} from `@tanstack/query-core`, with
|
|
230
|
+
* `mutate` narrowed to the fire-and-forget {@link UseMutateFunction} signature, plus the added `mutateAsync`.
|
|
231
|
+
*
|
|
232
|
+
* @template TData - The type your `mutationFn` resolves to.
|
|
233
|
+
* @template TError - The type of errors your `mutationFn` may throw.
|
|
234
|
+
* @template TVariables - The type of the variable passed to `mutate`/`mutateAsync`.
|
|
235
|
+
* @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as
|
|
236
|
+
* their `onMutateResult` parameter — useful for optimistic-update rollback data.
|
|
237
|
+
*/
|
|
78
238
|
type UseBaseMutationResult<TData = unknown, TError = DefaultError, TVariables = unknown, TOnMutateResult = unknown> = Override<MutationObserverResult<TData, TError, TVariables, TOnMutateResult>, {
|
|
79
239
|
mutate: UseMutateFunction<TData, TError, TVariables, TOnMutateResult>;
|
|
80
240
|
}> & {
|
|
241
|
+
/**
|
|
242
|
+
* Similar to `mutate`, but returns a promise which can be awaited.
|
|
243
|
+
*/
|
|
81
244
|
mutateAsync: UseMutateAsyncFunction<TData, TError, TVariables, TOnMutateResult>;
|
|
82
245
|
};
|
|
246
|
+
/**
|
|
247
|
+
* The result of `useMutation`. Same as {@link UseBaseMutationResult}.
|
|
248
|
+
*
|
|
249
|
+
* @template TData - The type your `mutationFn` resolves to.
|
|
250
|
+
* @template TError - The type of errors your `mutationFn` may throw.
|
|
251
|
+
* @template TVariables - The type of the variable passed to `mutate`/`mutateAsync`.
|
|
252
|
+
* @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as
|
|
253
|
+
* their `onMutateResult` parameter — useful for optimistic-update rollback data.
|
|
254
|
+
*/
|
|
83
255
|
type UseMutationResult<TData = unknown, TError = DefaultError, TVariables = unknown, TOnMutateResult = unknown> = UseBaseMutationResult<TData, TError, TVariables, TOnMutateResult>;
|
|
84
256
|
//#endregion
|
|
85
257
|
//#region src/queryOptions.d.ts
|
|
258
|
+
/**
|
|
259
|
+
* The options accepted by the `queryOptions` overload selected when no `initialData` is set — `data` may be
|
|
260
|
+
* `undefined` while the query is `pending`. `queryOptions` itself accepts and returns a plain object (its
|
|
261
|
+
* parameter type is `ReturnType<UndefinedInitialDataOptions<...>>`, i.e. this `Accessor` called); Solid's
|
|
262
|
+
* reactivity applies where the result is consumed instead, e.g. `useQuery(() => options)`.
|
|
263
|
+
*
|
|
264
|
+
* @template TQueryFnData - The type your `queryFn` resolves to.
|
|
265
|
+
* @template TError - The type of errors your `queryFn` may throw.
|
|
266
|
+
* @template TData - The type `data` ends up as after `select` runs.
|
|
267
|
+
* @template TQueryKey - The type of your `queryKey`.
|
|
268
|
+
*/
|
|
86
269
|
type UndefinedInitialDataOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey> = Accessor<QueryOptions<TQueryFnData, TError, TData, TQueryKey> & {
|
|
87
270
|
initialData?: undefined;
|
|
88
271
|
}>;
|
|
272
|
+
/**
|
|
273
|
+
* The options accepted by the `queryOptions` overload selected when `initialData` is set — `data` is never
|
|
274
|
+
* `undefined`.
|
|
275
|
+
*
|
|
276
|
+
* @template TQueryFnData - The type your `queryFn` resolves to.
|
|
277
|
+
* @template TError - The type of errors your `queryFn` may throw.
|
|
278
|
+
* @template TData - The type `data` ends up as after `select` runs.
|
|
279
|
+
* @template TQueryKey - The type of your `queryKey`.
|
|
280
|
+
*/
|
|
89
281
|
type DefinedInitialDataOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey> = Accessor<QueryOptions<TQueryFnData, TError, TData, TQueryKey> & {
|
|
90
282
|
initialData: TQueryFnData | (() => TQueryFnData);
|
|
91
283
|
}>;
|
|
92
|
-
|
|
284
|
+
/**
|
|
285
|
+
* You can generally pass everything to `queryOptions` that you can also pass to `useQuery`. These options can
|
|
286
|
+
* be shared across hooks and imperative APIs such as `queryClient.query`. `options.queryKey` is required and
|
|
287
|
+
* is the query key to generate options for.
|
|
288
|
+
*
|
|
289
|
+
* This overload is selected when `initialData` is set, so the resulting `data` is never `undefined`.
|
|
290
|
+
*
|
|
291
|
+
* @see {@link useQuery} to run a query with these options.
|
|
292
|
+
* @param options - The {@link DefinedInitialDataOptions} to use — everything you can pass to `useQuery`, with `initialData` set.
|
|
293
|
+
* @returns The same options object, typed so that `queryKey` carries the inferred data type.
|
|
294
|
+
*
|
|
295
|
+
* @example
|
|
296
|
+
* ```tsx
|
|
297
|
+
* import { For } from 'solid-js'
|
|
298
|
+
* import { queryOptions, useQuery } from '@tanstack/solid-query'
|
|
299
|
+
*
|
|
300
|
+
* const postsOptions = queryOptions({
|
|
301
|
+
* queryKey: ['posts'],
|
|
302
|
+
* queryFn: fetchPosts,
|
|
303
|
+
* initialData: [],
|
|
304
|
+
* })
|
|
305
|
+
*
|
|
306
|
+
* function Posts() {
|
|
307
|
+
* // `postsQuery.data` is `Post[]`, never `undefined`, thanks to `initialData` — even if a refetch fails,
|
|
308
|
+
* // so the list stays visible alongside the error.
|
|
309
|
+
* const postsQuery = useQuery(() => postsOptions)
|
|
310
|
+
*
|
|
311
|
+
* return (
|
|
312
|
+
* <div>
|
|
313
|
+
* {postsQuery.isError ? <span>Error: {postsQuery.error.message}</span> : null}
|
|
314
|
+
* <ul>
|
|
315
|
+
* <For each={postsQuery.data}>{(post) => <li>{post.title}</li>}</For>
|
|
316
|
+
* </ul>
|
|
317
|
+
* </div>
|
|
318
|
+
* )
|
|
319
|
+
* }
|
|
320
|
+
* ```
|
|
321
|
+
*/
|
|
93
322
|
declare function queryOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: ReturnType<DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>>): ReturnType<DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>> & QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>;
|
|
323
|
+
/**
|
|
324
|
+
* You can generally pass everything to `queryOptions` that you can also pass to `useQuery`. These options can
|
|
325
|
+
* be shared across hooks and imperative APIs such as `queryClient.query`. `options.queryKey` is required and
|
|
326
|
+
* is the query key to generate options for.
|
|
327
|
+
*
|
|
328
|
+
* @see {@link useQuery} to run a query with these options.
|
|
329
|
+
* @param options - The {@link UndefinedInitialDataOptions} to use — everything you can pass to `useQuery`.
|
|
330
|
+
* @returns The same options object, typed so that `queryKey` carries the inferred data type.
|
|
331
|
+
*
|
|
332
|
+
* @example
|
|
333
|
+
* A parameterized factory, so the same options object can be reused per `id`:
|
|
334
|
+
* ```tsx
|
|
335
|
+
* import { Match, Switch } from 'solid-js'
|
|
336
|
+
* import { queryOptions, useQuery } from '@tanstack/solid-query'
|
|
337
|
+
*
|
|
338
|
+
* const postOptions = (id: string) =>
|
|
339
|
+
* queryOptions({
|
|
340
|
+
* queryKey: ['post', id],
|
|
341
|
+
* queryFn: () => fetchPost(id),
|
|
342
|
+
* })
|
|
343
|
+
*
|
|
344
|
+
* function Post(props: { id: string }) {
|
|
345
|
+
* const postQuery = useQuery(() => postOptions(props.id))
|
|
346
|
+
*
|
|
347
|
+
* return (
|
|
348
|
+
* <Switch>
|
|
349
|
+
* <Match when={postQuery.isPending}>Loading...</Match>
|
|
350
|
+
* <Match when={postQuery.isError}>Error: {postQuery.error.message}</Match>
|
|
351
|
+
* <Match when={postQuery.isSuccess}>
|
|
352
|
+
* <h1>{postQuery.data.title}</h1>
|
|
353
|
+
* </Match>
|
|
354
|
+
* </Switch>
|
|
355
|
+
* )
|
|
356
|
+
* }
|
|
357
|
+
* ```
|
|
358
|
+
*/
|
|
359
|
+
declare function queryOptions<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: ReturnType<UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>>): ReturnType<UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>> & QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>;
|
|
94
360
|
//#endregion
|
|
95
361
|
//#region src/useQuery.d.ts
|
|
362
|
+
/**
|
|
363
|
+
* @see {@link queryOptions} to share these options between `useQuery` and imperative APIs like `queryClient.query`.
|
|
364
|
+
* @param options - An accessor returning the {@link UndefinedInitialDataOptions} to use — everything you can
|
|
365
|
+
* pass to `useQuery`.
|
|
366
|
+
* @param queryClient - An accessor for a custom `QueryClient`. Otherwise, the one from the nearest context
|
|
367
|
+
* will be used.
|
|
368
|
+
* @returns The current query result, as a Solid store. `status` is `pending` if there is no cached data to
|
|
369
|
+
* display, `error` if the last fetch attempt failed, or `success` if the query has data to display.
|
|
370
|
+
* `isPending`/`isSuccess`/`isError` are derived booleans for convenience.
|
|
371
|
+
*
|
|
372
|
+
* @example
|
|
373
|
+
* ```tsx
|
|
374
|
+
* import { For, Match, Switch } from 'solid-js'
|
|
375
|
+
* import { useQuery } from '@tanstack/solid-query'
|
|
376
|
+
*
|
|
377
|
+
* function Posts() {
|
|
378
|
+
* const postsQuery = useQuery(() => ({
|
|
379
|
+
* queryKey: ['posts'],
|
|
380
|
+
* queryFn: fetchPosts,
|
|
381
|
+
* }))
|
|
382
|
+
*
|
|
383
|
+
* return (
|
|
384
|
+
* <Switch>
|
|
385
|
+
* <Match when={postsQuery.isPending}>Loading...</Match>
|
|
386
|
+
* <Match when={postsQuery.isError}>Error: {postsQuery.error.message}</Match>
|
|
387
|
+
* <Match when={postsQuery.isSuccess}>
|
|
388
|
+
* <ul>
|
|
389
|
+
* <For each={postsQuery.data}>{(post) => <li>{post.title}</li>}</For>
|
|
390
|
+
* </ul>
|
|
391
|
+
* <div>{postsQuery.isFetching ? 'Background Updating...' : ' '}</div>
|
|
392
|
+
* </Match>
|
|
393
|
+
* </Switch>
|
|
394
|
+
* )
|
|
395
|
+
* }
|
|
396
|
+
* ```
|
|
397
|
+
*
|
|
398
|
+
* @example
|
|
399
|
+
* `select` derives whatever `data` a component needs from the cached value, without changing what's
|
|
400
|
+
* actually stored in the cache — the cache still holds the full `Post[]`, but `data` here is a `number`:
|
|
401
|
+
* ```tsx
|
|
402
|
+
* import { Match, Switch } from 'solid-js'
|
|
403
|
+
* import { useQuery } from '@tanstack/solid-query'
|
|
404
|
+
*
|
|
405
|
+
* function PostCount() {
|
|
406
|
+
* const postsQuery = useQuery(() => ({
|
|
407
|
+
* queryKey: ['posts'],
|
|
408
|
+
* queryFn: fetchPosts,
|
|
409
|
+
* select: (posts) => posts.length,
|
|
410
|
+
* }))
|
|
411
|
+
*
|
|
412
|
+
* return (
|
|
413
|
+
* <Switch>
|
|
414
|
+
* <Match when={postsQuery.isPending}>Loading...</Match>
|
|
415
|
+
* <Match when={postsQuery.isError}>Error: {postsQuery.error.message}</Match>
|
|
416
|
+
* <Match when={postsQuery.isSuccess}>{postsQuery.data} posts</Match>
|
|
417
|
+
* </Switch>
|
|
418
|
+
* )
|
|
419
|
+
* }
|
|
420
|
+
* ```
|
|
421
|
+
*
|
|
422
|
+
* @example
|
|
423
|
+
* A dependent query, only enabled once `postId` is set:
|
|
424
|
+
* ```tsx
|
|
425
|
+
* import { Match, Switch } from 'solid-js'
|
|
426
|
+
* import { useQuery } from '@tanstack/solid-query'
|
|
427
|
+
*
|
|
428
|
+
* function Post(props: { postId: number | undefined }) {
|
|
429
|
+
* const postQuery = useQuery(() => ({
|
|
430
|
+
* queryKey: ['post', props.postId],
|
|
431
|
+
* queryFn: () => fetchPost(props.postId!),
|
|
432
|
+
* enabled: props.postId != null,
|
|
433
|
+
* }))
|
|
434
|
+
*
|
|
435
|
+
* return (
|
|
436
|
+
* <Switch fallback={<h1>{postQuery.data?.title}</h1>}>
|
|
437
|
+
* <Match when={props.postId == null}>Select a post</Match>
|
|
438
|
+
* <Match when={postQuery.isLoading}>Loading...</Match>
|
|
439
|
+
* <Match when={postQuery.isError}>Error: {postQuery.error.message}</Match>
|
|
440
|
+
* </Switch>
|
|
441
|
+
* )
|
|
442
|
+
* }
|
|
443
|
+
* ```
|
|
444
|
+
*
|
|
445
|
+
* @example
|
|
446
|
+
* The same dependent query, using `skipToken` to disable it in a type-safe way instead of relying on
|
|
447
|
+
* `enabled`. The non-null assertion is still needed — Solid's `props` narrowing doesn't survive into the
|
|
448
|
+
* `queryFn` closure the way a local `const` would — but `skipToken` keeps `queryFn`'s return type accurate
|
|
449
|
+
* without it. `refetch` doesn't work while `queryFn` is `skipToken` — use `enabled: false` instead if you
|
|
450
|
+
* need to trigger the query manually:
|
|
451
|
+
* ```tsx
|
|
452
|
+
* import { Match, Switch } from 'solid-js'
|
|
453
|
+
* import { skipToken, useQuery } from '@tanstack/solid-query'
|
|
454
|
+
*
|
|
455
|
+
* function Post(props: { postId: number | undefined }) {
|
|
456
|
+
* const postQuery = useQuery(() => ({
|
|
457
|
+
* queryKey: ['post', props.postId],
|
|
458
|
+
* queryFn: props.postId != null ? () => fetchPost(props.postId!) : skipToken,
|
|
459
|
+
* }))
|
|
460
|
+
*
|
|
461
|
+
* return (
|
|
462
|
+
* <Switch fallback={<h1>{postQuery.data?.title}</h1>}>
|
|
463
|
+
* <Match when={props.postId == null}>Select a post</Match>
|
|
464
|
+
* <Match when={postQuery.isLoading}>Loading...</Match>
|
|
465
|
+
* <Match when={postQuery.isError}>Error: {postQuery.error.message}</Match>
|
|
466
|
+
* </Switch>
|
|
467
|
+
* )
|
|
468
|
+
* }
|
|
469
|
+
* ```
|
|
470
|
+
*
|
|
471
|
+
* @example
|
|
472
|
+
* Seeding a detail query from an already-cached list, to skip the loading state:
|
|
473
|
+
* ```tsx
|
|
474
|
+
* import { useQuery, useQueryClient } from '@tanstack/solid-query'
|
|
475
|
+
*
|
|
476
|
+
* function Post(props: { postId: number }) {
|
|
477
|
+
* const queryClient = useQueryClient()
|
|
478
|
+
*
|
|
479
|
+
* const postQuery = useQuery(() => ({
|
|
480
|
+
* queryKey: ['post', props.postId],
|
|
481
|
+
* queryFn: () => fetchPost(props.postId),
|
|
482
|
+
* initialData: () =>
|
|
483
|
+
* queryClient
|
|
484
|
+
* .getQueryData<Array<Post>>(['posts'])
|
|
485
|
+
* ?.find((post) => post.id === props.postId),
|
|
486
|
+
* }))
|
|
487
|
+
*
|
|
488
|
+
* return postQuery.isError ? <span>Error: {postQuery.error.message}</span> : <h1>{postQuery.data?.title}</h1>
|
|
489
|
+
* }
|
|
490
|
+
* ```
|
|
491
|
+
*
|
|
492
|
+
* @example
|
|
493
|
+
* Paginated data, keeping the previous page's data visible while the next page loads:
|
|
494
|
+
* ```tsx
|
|
495
|
+
* import { For, createSignal } from 'solid-js'
|
|
496
|
+
* import { keepPreviousData, useQuery } from '@tanstack/solid-query'
|
|
497
|
+
*
|
|
498
|
+
* function Posts() {
|
|
499
|
+
* const [page, setPage] = createSignal(0)
|
|
500
|
+
*
|
|
501
|
+
* const postsQuery = useQuery(() => ({
|
|
502
|
+
* queryKey: ['posts', page()],
|
|
503
|
+
* queryFn: () => fetchPosts(page()),
|
|
504
|
+
* placeholderData: keepPreviousData,
|
|
505
|
+
* }))
|
|
506
|
+
*
|
|
507
|
+
* return (
|
|
508
|
+
* <div>
|
|
509
|
+
* <ul>
|
|
510
|
+
* <For each={postsQuery.data}>{(post) => <li>{post.title}</li>}</For>
|
|
511
|
+
* </ul>
|
|
512
|
+
* <button
|
|
513
|
+
* disabled={postsQuery.isPlaceholderData}
|
|
514
|
+
* onClick={() => setPage((old) => old + 1)}
|
|
515
|
+
* >
|
|
516
|
+
* Next Page
|
|
517
|
+
* </button>
|
|
518
|
+
* </div>
|
|
519
|
+
* )
|
|
520
|
+
* }
|
|
521
|
+
* ```
|
|
522
|
+
*/
|
|
96
523
|
declare function useQuery<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>, queryClient?: () => QueryClient): UseQueryResult<TData, TError>;
|
|
524
|
+
/**
|
|
525
|
+
* This overload is selected when `initialData` is set, so the resulting `data` is never `undefined`.
|
|
526
|
+
*
|
|
527
|
+
* @see {@link queryOptions} to share these options between `useQuery` and imperative APIs like `queryClient.query`.
|
|
528
|
+
* @param options - An accessor returning the {@link DefinedInitialDataOptions} to use — everything you can
|
|
529
|
+
* pass to `useQuery`, with `initialData` set.
|
|
530
|
+
* @param queryClient - An accessor for a custom `QueryClient`. Otherwise, the one from the nearest context
|
|
531
|
+
* will be used.
|
|
532
|
+
* @returns The current query result, as a Solid store, typed so that `status` is `success` — or `error` if a
|
|
533
|
+
* fetch attempt fails while keeping the existing data (`status` never resolves to `pending` in this overload's
|
|
534
|
+
* type, since `initialData` guarantees data upfront). `isSuccess`/`isError` are derived booleans for
|
|
535
|
+
* convenience.
|
|
536
|
+
*
|
|
537
|
+
* @example
|
|
538
|
+
* ```tsx
|
|
539
|
+
* import { For } from 'solid-js'
|
|
540
|
+
* import { useQuery } from '@tanstack/solid-query'
|
|
541
|
+
*
|
|
542
|
+
* function Posts() {
|
|
543
|
+
* // `postsQuery.data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the
|
|
544
|
+
* // list stays visible alongside the error.
|
|
545
|
+
* const postsQuery = useQuery(() => ({
|
|
546
|
+
* queryKey: ['posts'],
|
|
547
|
+
* queryFn: fetchPosts,
|
|
548
|
+
* initialData: [],
|
|
549
|
+
* }))
|
|
550
|
+
*
|
|
551
|
+
* return (
|
|
552
|
+
* <div>
|
|
553
|
+
* {postsQuery.isError ? <span>Error: {postsQuery.error.message}</span> : null}
|
|
554
|
+
* <ul>
|
|
555
|
+
* <For each={postsQuery.data}>{(post) => <li>{post.title}</li>}</For>
|
|
556
|
+
* </ul>
|
|
557
|
+
* </div>
|
|
558
|
+
* )
|
|
559
|
+
* }
|
|
560
|
+
* ```
|
|
561
|
+
*/
|
|
97
562
|
declare function useQuery<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>, queryClient?: () => QueryClient): DefinedUseQueryResult<TData, TError>;
|
|
98
563
|
//#endregion
|
|
99
564
|
//#region src/infiniteQueryOptions.d.ts
|
|
565
|
+
/**
|
|
566
|
+
* The options accepted by the `infiniteQueryOptions` overload selected when no `initialData` is set — `data`
|
|
567
|
+
* may be `undefined` while the query is `pending`. `infiniteQueryOptions` itself accepts and returns a plain
|
|
568
|
+
* object (its parameter type is `ReturnType<UndefinedInitialDataInfiniteOptions<...>>`, i.e. this `Accessor`
|
|
569
|
+
* called); Solid's reactivity applies where the result is consumed instead, e.g.
|
|
570
|
+
* `useInfiniteQuery(() => options)`.
|
|
571
|
+
*
|
|
572
|
+
* @template TQueryFnData - The type of a single page, as your `queryFn` resolves it.
|
|
573
|
+
* @template TError - The type of errors your `queryFn` may throw.
|
|
574
|
+
* @template TData - The type `data` ends up as after `select` runs — defaults to `InfiniteData<TQueryFnData>`,
|
|
575
|
+
* the shape of all fetched pages plus their page params.
|
|
576
|
+
* @template TQueryKey - The type of your `queryKey`.
|
|
577
|
+
* @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page.
|
|
578
|
+
*/
|
|
100
579
|
type UndefinedInitialDataInfiniteOptions<TQueryFnData, TError = DefaultError, TData = InfiniteData<TQueryFnData>, TQueryKey extends QueryKey = QueryKey, TPageParam = unknown> = Accessor<InfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam> & {
|
|
101
580
|
initialData?: undefined;
|
|
102
581
|
}>;
|
|
582
|
+
/**
|
|
583
|
+
* The options accepted by the `infiniteQueryOptions` overload selected when `initialData` is set — `data` is
|
|
584
|
+
* never `undefined`.
|
|
585
|
+
*
|
|
586
|
+
* @template TQueryFnData - The type of a single page, as your `queryFn` resolves it.
|
|
587
|
+
* @template TError - The type of errors your `queryFn` may throw.
|
|
588
|
+
* @template TData - The type `data` ends up as after `select` runs — defaults to `InfiniteData<TQueryFnData>`,
|
|
589
|
+
* the shape of all fetched pages plus their page params.
|
|
590
|
+
* @template TQueryKey - The type of your `queryKey`.
|
|
591
|
+
* @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page.
|
|
592
|
+
*/
|
|
103
593
|
type DefinedInitialDataInfiniteOptions<TQueryFnData, TError = DefaultError, TData = InfiniteData<TQueryFnData>, TQueryKey extends QueryKey = QueryKey, TPageParam = unknown> = Accessor<InfiniteQueryOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam> & {
|
|
104
594
|
initialData: NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>> | (() => NonUndefinedGuard<InfiniteData<TQueryFnData, TPageParam>>);
|
|
105
595
|
}>;
|
|
596
|
+
/**
|
|
597
|
+
* You can generally pass everything to `infiniteQueryOptions` that you can also pass to `useInfiniteQuery`.
|
|
598
|
+
* These options can be shared across hooks and imperative APIs such as `queryClient.infiniteQuery`.
|
|
599
|
+
* `options.queryKey` is required and is the query key to generate options for.
|
|
600
|
+
*
|
|
601
|
+
* This overload is selected when `initialData` is set.
|
|
602
|
+
*
|
|
603
|
+
* @see {@link useInfiniteQuery} to run an infinite query with these options.
|
|
604
|
+
* @param options - The {@link DefinedInitialDataInfiniteOptions} to use — everything you can pass to `useInfiniteQuery`, with `initialData` set.
|
|
605
|
+
* @returns The same options object, typed so that `queryKey` carries the inferred data type.
|
|
606
|
+
*
|
|
607
|
+
* @example
|
|
608
|
+
* ```tsx
|
|
609
|
+
* import { For } from 'solid-js'
|
|
610
|
+
* import { infiniteQueryOptions, useInfiniteQuery } from '@tanstack/solid-query'
|
|
611
|
+
*
|
|
612
|
+
* const projectsOptions = infiniteQueryOptions({
|
|
613
|
+
* queryKey: ['projects'],
|
|
614
|
+
* queryFn: ({ pageParam }) => fetchProjects(pageParam),
|
|
615
|
+
* initialPageParam: 0,
|
|
616
|
+
* getNextPageParam: (lastPage) => lastPage.nextId,
|
|
617
|
+
* initialData: { pages: [], pageParams: [] },
|
|
618
|
+
* })
|
|
619
|
+
*
|
|
620
|
+
* function Projects() {
|
|
621
|
+
* // `projectsQuery.data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the
|
|
622
|
+
* // list stays visible alongside the error.
|
|
623
|
+
* const projectsQuery = useInfiniteQuery(() => projectsOptions)
|
|
624
|
+
*
|
|
625
|
+
* return (
|
|
626
|
+
* <div>
|
|
627
|
+
* {projectsQuery.isError ? <span>Error: {projectsQuery.error.message}</span> : null}
|
|
628
|
+
* <ul>
|
|
629
|
+
* <For each={projectsQuery.data.pages}>
|
|
630
|
+
* {(page) => <For each={page.projects}>{(p) => <li>{p.name}</li>}</For>}
|
|
631
|
+
* </For>
|
|
632
|
+
* </ul>
|
|
633
|
+
* </div>
|
|
634
|
+
* )
|
|
635
|
+
* }
|
|
636
|
+
* ```
|
|
637
|
+
*/
|
|
106
638
|
declare function infiniteQueryOptions<TQueryFnData, TError = DefaultError, TData = InfiniteData<TQueryFnData>, TQueryKey extends QueryKey = QueryKey, TPageParam = unknown>(options: ReturnType<DefinedInitialDataInfiniteOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>>): ReturnType<DefinedInitialDataInfiniteOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>> & QueryKeyWithDataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>;
|
|
639
|
+
/**
|
|
640
|
+
* You can generally pass everything to `infiniteQueryOptions` that you can also pass to `useInfiniteQuery`.
|
|
641
|
+
* These options can be shared across hooks and imperative APIs such as `queryClient.infiniteQuery`.
|
|
642
|
+
* `options.queryKey` is required and is the query key to generate options for.
|
|
643
|
+
*
|
|
644
|
+
* @see {@link useInfiniteQuery} to run an infinite query with these options.
|
|
645
|
+
* @param options - The {@link UndefinedInitialDataInfiniteOptions} to use — everything you can pass to `useInfiniteQuery`.
|
|
646
|
+
* @returns The same options object, typed so that `queryKey` carries the inferred data type.
|
|
647
|
+
*
|
|
648
|
+
* @example
|
|
649
|
+
* A parameterized factory, so the same options object can be reused per `postId`:
|
|
650
|
+
* ```tsx
|
|
651
|
+
* import { For, Match, Switch } from 'solid-js'
|
|
652
|
+
* import { infiniteQueryOptions, useInfiniteQuery } from '@tanstack/solid-query'
|
|
653
|
+
*
|
|
654
|
+
* const commentsOptions = (postId: string) =>
|
|
655
|
+
* infiniteQueryOptions({
|
|
656
|
+
* queryKey: ['post', postId, 'comments'],
|
|
657
|
+
* queryFn: ({ pageParam }) => fetchComments(postId, pageParam),
|
|
658
|
+
* initialPageParam: 0,
|
|
659
|
+
* getNextPageParam: (lastPage) => lastPage.nextId,
|
|
660
|
+
* })
|
|
661
|
+
*
|
|
662
|
+
* function Comments(props: { postId: string }) {
|
|
663
|
+
* const commentsQuery = useInfiniteQuery(() => commentsOptions(props.postId))
|
|
664
|
+
*
|
|
665
|
+
* return (
|
|
666
|
+
* <Switch>
|
|
667
|
+
* <Match when={commentsQuery.isPending}>Loading...</Match>
|
|
668
|
+
* <Match when={commentsQuery.isError}>Error: {commentsQuery.error.message}</Match>
|
|
669
|
+
* <Match when={commentsQuery.isSuccess}>
|
|
670
|
+
* <ul>
|
|
671
|
+
* <For each={commentsQuery.data.pages}>
|
|
672
|
+
* {(page) => <For each={page.comments}>{(c) => <li>{c.text}</li>}</For>}
|
|
673
|
+
* </For>
|
|
674
|
+
* </ul>
|
|
675
|
+
* </Match>
|
|
676
|
+
* </Switch>
|
|
677
|
+
* )
|
|
678
|
+
* }
|
|
679
|
+
* ```
|
|
680
|
+
*/
|
|
107
681
|
declare function infiniteQueryOptions<TQueryFnData, TError = DefaultError, TData = InfiniteData<TQueryFnData>, TQueryKey extends QueryKey = QueryKey, TPageParam = unknown>(options: ReturnType<UndefinedInitialDataInfiniteOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>>): ReturnType<UndefinedInitialDataInfiniteOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>> & QueryKeyWithDataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>;
|
|
108
682
|
//#endregion
|
|
109
683
|
//#region src/useInfiniteQuery.d.ts
|
|
684
|
+
/**
|
|
685
|
+
* The options for `useInfiniteQuery` are identical to `useQuery`, with the addition of
|
|
686
|
+
* `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, and `maxPages`.
|
|
687
|
+
*
|
|
688
|
+
* This overload is selected when `initialData` is set.
|
|
689
|
+
*
|
|
690
|
+
* @remarks Keep in mind that imperative fetch calls, such as `fetchNextPage`, may interfere with the default
|
|
691
|
+
* refetch behavior, resulting in outdated data. Make sure to call these functions only in response to user
|
|
692
|
+
* actions, or add conditions like `hasNextPage && !isFetching`.
|
|
693
|
+
* @see {@link infiniteQueryOptions} to share these options between `useInfiniteQuery` and imperative APIs like `queryClient.infiniteQuery`.
|
|
694
|
+
* @param options - An accessor returning the {@link DefinedInitialDataInfiniteOptions} to use — everything you
|
|
695
|
+
* can pass to `useInfiniteQuery`, with `initialData` set.
|
|
696
|
+
* @param queryClient - An accessor for a custom `QueryClient`. Otherwise, the one from the nearest context
|
|
697
|
+
* will be used.
|
|
698
|
+
* @returns The same properties as `useQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`,
|
|
699
|
+
* `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data.pages` and
|
|
700
|
+
* `data.pageParams` are also added, as long as a `select` doesn't change `TData` away from its default
|
|
701
|
+
* `InfiniteData<TQueryFnData>` shape.
|
|
702
|
+
*
|
|
703
|
+
* @example
|
|
704
|
+
* ```tsx
|
|
705
|
+
* import { For } from 'solid-js'
|
|
706
|
+
* import { useInfiniteQuery } from '@tanstack/solid-query'
|
|
707
|
+
*
|
|
708
|
+
* function Projects() {
|
|
709
|
+
* // `projectsQuery.data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the
|
|
710
|
+
* // list stays visible alongside the error.
|
|
711
|
+
* const projectsQuery = useInfiniteQuery(() => ({
|
|
712
|
+
* queryKey: ['projects'],
|
|
713
|
+
* queryFn: ({ pageParam }) => fetchProjects(pageParam),
|
|
714
|
+
* initialPageParam: 0,
|
|
715
|
+
* getNextPageParam: (lastPage) => lastPage.nextId,
|
|
716
|
+
* initialData: { pages: [], pageParams: [] },
|
|
717
|
+
* }))
|
|
718
|
+
*
|
|
719
|
+
* return (
|
|
720
|
+
* <div>
|
|
721
|
+
* {projectsQuery.isError ? <span>Error: {projectsQuery.error.message}</span> : null}
|
|
722
|
+
* <ul>
|
|
723
|
+
* <For each={projectsQuery.data.pages}>
|
|
724
|
+
* {(page) => <For each={page.projects}>{(p) => <li>{p.name}</li>}</For>}
|
|
725
|
+
* </For>
|
|
726
|
+
* </ul>
|
|
727
|
+
* </div>
|
|
728
|
+
* )
|
|
729
|
+
* }
|
|
730
|
+
* ```
|
|
731
|
+
*/
|
|
110
732
|
declare function useInfiniteQuery<TQueryFnData, TError = DefaultError, TData = InfiniteData<TQueryFnData>, TQueryKey extends QueryKey = QueryKey, TPageParam = unknown>(options: DefinedInitialDataInfiniteOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>, queryClient?: Accessor<QueryClient>): DefinedUseInfiniteQueryResult<TData, TError>;
|
|
733
|
+
/**
|
|
734
|
+
* The options for `useInfiniteQuery` are identical to `useQuery`, with the addition of
|
|
735
|
+
* `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, and `maxPages`.
|
|
736
|
+
*
|
|
737
|
+
* @remarks Keep in mind that imperative fetch calls, such as `fetchNextPage`, may interfere with the default
|
|
738
|
+
* refetch behavior, resulting in outdated data. Make sure to call these functions only in response to user
|
|
739
|
+
* actions, or add conditions like `hasNextPage && !isFetching`.
|
|
740
|
+
* @see {@link infiniteQueryOptions} to share these options between `useInfiniteQuery` and imperative APIs like `queryClient.infiniteQuery`.
|
|
741
|
+
* @param options - An accessor returning the {@link UndefinedInitialDataInfiniteOptions} to use — everything
|
|
742
|
+
* you can pass to `useInfiniteQuery`.
|
|
743
|
+
* @param queryClient - An accessor for a custom `QueryClient`. Otherwise, the one from the nearest context
|
|
744
|
+
* will be used.
|
|
745
|
+
* @returns The same properties as `useQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`,
|
|
746
|
+
* `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data.pages` and
|
|
747
|
+
* `data.pageParams` are also added, as long as a `select` doesn't change `TData` away from its default
|
|
748
|
+
* `InfiniteData<TQueryFnData>` shape.
|
|
749
|
+
*
|
|
750
|
+
* @example
|
|
751
|
+
* Fetching the next page from a "Load More" button click:
|
|
752
|
+
* ```tsx
|
|
753
|
+
* import { For, Match, Switch } from 'solid-js'
|
|
754
|
+
* import { useInfiniteQuery } from '@tanstack/solid-query'
|
|
755
|
+
*
|
|
756
|
+
* function Projects() {
|
|
757
|
+
* const projectsQuery = useInfiniteQuery(() => ({
|
|
758
|
+
* queryKey: ['projects'],
|
|
759
|
+
* queryFn: ({ pageParam }) => fetchProjects(pageParam),
|
|
760
|
+
* initialPageParam: 0,
|
|
761
|
+
* getNextPageParam: (lastPage) => lastPage.nextId,
|
|
762
|
+
* }))
|
|
763
|
+
*
|
|
764
|
+
* return (
|
|
765
|
+
* <Switch>
|
|
766
|
+
* <Match when={projectsQuery.isPending}>Loading...</Match>
|
|
767
|
+
* <Match when={projectsQuery.isError}>Error: {projectsQuery.error.message}</Match>
|
|
768
|
+
* <Match when={projectsQuery.isSuccess}>
|
|
769
|
+
* <ul>
|
|
770
|
+
* <For each={projectsQuery.data.pages}>
|
|
771
|
+
* {(page) => <For each={page.projects}>{(p) => <li>{p.name}</li>}</For>}
|
|
772
|
+
* </For>
|
|
773
|
+
* </ul>
|
|
774
|
+
* <button
|
|
775
|
+
* onClick={() => projectsQuery.fetchNextPage()}
|
|
776
|
+
* disabled={!projectsQuery.hasNextPage || projectsQuery.isFetching}
|
|
777
|
+
* >
|
|
778
|
+
* {projectsQuery.isFetchingNextPage
|
|
779
|
+
* ? 'Loading more...'
|
|
780
|
+
* : projectsQuery.hasNextPage
|
|
781
|
+
* ? 'Load More'
|
|
782
|
+
* : 'Nothing more to load'}
|
|
783
|
+
* </button>
|
|
784
|
+
* </Match>
|
|
785
|
+
* </Switch>
|
|
786
|
+
* )
|
|
787
|
+
* }
|
|
788
|
+
* ```
|
|
789
|
+
*
|
|
790
|
+
* @example
|
|
791
|
+
* Fetching the next page automatically as the user scrolls, using an `IntersectionObserver` on a
|
|
792
|
+
* sentinel element after the list:
|
|
793
|
+
* ```tsx
|
|
794
|
+
* import { For, Match, Switch, createEffect, onCleanup } from 'solid-js'
|
|
795
|
+
* import { useInfiniteQuery } from '@tanstack/solid-query'
|
|
796
|
+
*
|
|
797
|
+
* function Projects() {
|
|
798
|
+
* const projectsQuery = useInfiniteQuery(() => ({
|
|
799
|
+
* queryKey: ['projects'],
|
|
800
|
+
* queryFn: ({ pageParam }) => fetchProjects(pageParam),
|
|
801
|
+
* initialPageParam: 0,
|
|
802
|
+
* getNextPageParam: (lastPage) => lastPage.nextId,
|
|
803
|
+
* }))
|
|
804
|
+
*
|
|
805
|
+
* let sentinelRef: HTMLDivElement | undefined
|
|
806
|
+
*
|
|
807
|
+
* createEffect(() => {
|
|
808
|
+
* if (sentinelRef == null || !projectsQuery.hasNextPage || projectsQuery.isFetching) return
|
|
809
|
+
*
|
|
810
|
+
* const observer = new IntersectionObserver(([entry]) => {
|
|
811
|
+
* if (entry?.isIntersecting) projectsQuery.fetchNextPage()
|
|
812
|
+
* })
|
|
813
|
+
* observer.observe(sentinelRef)
|
|
814
|
+
*
|
|
815
|
+
* onCleanup(() => observer.disconnect())
|
|
816
|
+
* })
|
|
817
|
+
*
|
|
818
|
+
* return (
|
|
819
|
+
* <Switch>
|
|
820
|
+
* <Match when={projectsQuery.isPending}>Loading...</Match>
|
|
821
|
+
* <Match when={projectsQuery.isError}>Error: {projectsQuery.error.message}</Match>
|
|
822
|
+
* <Match when={projectsQuery.isSuccess}>
|
|
823
|
+
* <ul>
|
|
824
|
+
* <For each={projectsQuery.data.pages}>
|
|
825
|
+
* {(page) => <For each={page.projects}>{(p) => <li>{p.name}</li>}</For>}
|
|
826
|
+
* </For>
|
|
827
|
+
* </ul>
|
|
828
|
+
* <div ref={sentinelRef}>{projectsQuery.isFetchingNextPage ? 'Loading more...' : null}</div>
|
|
829
|
+
* </Match>
|
|
830
|
+
* </Switch>
|
|
831
|
+
* )
|
|
832
|
+
* }
|
|
833
|
+
* ```
|
|
834
|
+
*/
|
|
111
835
|
declare function useInfiniteQuery<TQueryFnData, TError = DefaultError, TData = InfiniteData<TQueryFnData>, TQueryKey extends QueryKey = QueryKey, TPageParam = unknown>(options: UndefinedInitialDataInfiniteOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>, queryClient?: Accessor<QueryClient>): UseInfiniteQueryResult<TData, TError>;
|
|
112
836
|
//#endregion
|
|
113
837
|
//#region src/useMutation.d.ts
|
|
838
|
+
/**
|
|
839
|
+
* @param options - An accessor returning the {@link UseMutationOptions} to use.
|
|
840
|
+
* @param queryClient - An accessor for a custom `QueryClient`. Otherwise, the one from the nearest context
|
|
841
|
+
* will be used.
|
|
842
|
+
* @returns `mutate`/`mutateAsync` also accept per-call `onSuccess`/`onError`/`onSettled` callbacks as a second
|
|
843
|
+
* argument, useful for triggering call-site side effects (e.g. navigation) without coupling them to the shared
|
|
844
|
+
* mutation definition. Hook-level callbacks (passed to `options`) fire for every mutation; per-call callbacks
|
|
845
|
+
* fire only for the latest call you've made, and only while the component is still mounted — unmounting before
|
|
846
|
+
* the mutation settles removes the subscription and prevents them from firing.
|
|
847
|
+
*
|
|
848
|
+
* @example
|
|
849
|
+
* ```tsx
|
|
850
|
+
* import { useMutation, useQueryClient } from '@tanstack/solid-query'
|
|
851
|
+
*
|
|
852
|
+
* function TodoItem(props: { id: number }) {
|
|
853
|
+
* const queryClient = useQueryClient()
|
|
854
|
+
*
|
|
855
|
+
* const deleteTodoMutation = useMutation(() => ({
|
|
856
|
+
* mutationFn: deleteTodo,
|
|
857
|
+
* onSuccess: () => {
|
|
858
|
+
* queryClient.invalidateQueries({ queryKey: ['todos'] })
|
|
859
|
+
* },
|
|
860
|
+
* }))
|
|
861
|
+
*
|
|
862
|
+
* return (
|
|
863
|
+
* <button onClick={() => deleteTodoMutation.mutate({ id: props.id })} disabled={deleteTodoMutation.isPending}>
|
|
864
|
+
* Delete
|
|
865
|
+
* </button>
|
|
866
|
+
* )
|
|
867
|
+
* }
|
|
868
|
+
* ```
|
|
869
|
+
*
|
|
870
|
+
* @example
|
|
871
|
+
* Rendering the mutation's own state, rather than just firing it off:
|
|
872
|
+
* ```tsx
|
|
873
|
+
* import { Match, Switch } from 'solid-js'
|
|
874
|
+
* import { useMutation, useQueryClient } from '@tanstack/solid-query'
|
|
875
|
+
*
|
|
876
|
+
* function AddTodo() {
|
|
877
|
+
* const queryClient = useQueryClient()
|
|
878
|
+
*
|
|
879
|
+
* const addMutation = useMutation(() => ({
|
|
880
|
+
* mutationFn: addTodo,
|
|
881
|
+
* onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
|
|
882
|
+
* }))
|
|
883
|
+
*
|
|
884
|
+
* return (
|
|
885
|
+
* <Switch fallback={<button onClick={() => addMutation.mutate('Item')}>Add</button>}>
|
|
886
|
+
* <Match when={addMutation.isPending}>Adding todo...</Match>
|
|
887
|
+
* <Match when={addMutation.isError}>
|
|
888
|
+
* <div>An error occurred: {addMutation.error?.message}</div>
|
|
889
|
+
* <button onClick={() => addMutation.mutate('Item')}>Add</button>
|
|
890
|
+
* </Match>
|
|
891
|
+
* </Switch>
|
|
892
|
+
* )
|
|
893
|
+
* }
|
|
894
|
+
* ```
|
|
895
|
+
*
|
|
896
|
+
* @example
|
|
897
|
+
* Optimistic update via `onMutate`, rolling back on `onError`:
|
|
898
|
+
* ```tsx
|
|
899
|
+
* import { useMutation, useQueryClient } from '@tanstack/solid-query'
|
|
900
|
+
*
|
|
901
|
+
* function AddTodo() {
|
|
902
|
+
* const queryClient = useQueryClient()
|
|
903
|
+
*
|
|
904
|
+
* const addMutation = useMutation(() => ({
|
|
905
|
+
* mutationFn: addTodo,
|
|
906
|
+
* onMutate: async (newTodo) => {
|
|
907
|
+
* await queryClient.cancelQueries({ queryKey: ['todos'] })
|
|
908
|
+
* const previousTodos = queryClient.getQueryData<Array<string>>(['todos'])
|
|
909
|
+
*
|
|
910
|
+
* queryClient.setQueryData<Array<string>>(['todos'], (old) => [
|
|
911
|
+
* ...(old ?? []),
|
|
912
|
+
* newTodo,
|
|
913
|
+
* ])
|
|
914
|
+
*
|
|
915
|
+
* // Passed to `onError` as `onMutateResult` if the mutation fails.
|
|
916
|
+
* return { previousTodos }
|
|
917
|
+
* },
|
|
918
|
+
* onError: (_err, _newTodo, onMutateResult) => {
|
|
919
|
+
* queryClient.setQueryData(['todos'], onMutateResult?.previousTodos)
|
|
920
|
+
* },
|
|
921
|
+
* onSettled: () => {
|
|
922
|
+
* queryClient.invalidateQueries({ queryKey: ['todos'] })
|
|
923
|
+
* },
|
|
924
|
+
* }))
|
|
925
|
+
*
|
|
926
|
+
* return (
|
|
927
|
+
* <button onClick={() => addMutation.mutate('Item')}>Add</button>
|
|
928
|
+
* )
|
|
929
|
+
* }
|
|
930
|
+
* ```
|
|
931
|
+
*
|
|
932
|
+
* @example
|
|
933
|
+
* Callbacks passed per call to `mutate` only fire for the last call — `mutateAsync` gives you a
|
|
934
|
+
* promise per call instead, so you can wait for all of them when they succeed:
|
|
935
|
+
* ```tsx
|
|
936
|
+
* import { useMutation, useQueryClient } from '@tanstack/solid-query'
|
|
937
|
+
*
|
|
938
|
+
* function AddTodos() {
|
|
939
|
+
* const queryClient = useQueryClient()
|
|
940
|
+
*
|
|
941
|
+
* const addMutation = useMutation(() => ({
|
|
942
|
+
* mutationFn: addTodo,
|
|
943
|
+
* onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
|
|
944
|
+
* }))
|
|
945
|
+
*
|
|
946
|
+
* async function handleAddAll(todos: Array<string>) {
|
|
947
|
+
* try {
|
|
948
|
+
* await Promise.all(todos.map((todo) => addMutation.mutateAsync(todo)))
|
|
949
|
+
* } catch (error) {
|
|
950
|
+
* console.error('Failed to add todos:', error)
|
|
951
|
+
* }
|
|
952
|
+
* }
|
|
953
|
+
*
|
|
954
|
+
* return (
|
|
955
|
+
* <button onClick={() => handleAddAll(['Todo 1', 'Todo 2', 'Todo 3'])}>
|
|
956
|
+
* Add all
|
|
957
|
+
* </button>
|
|
958
|
+
* )
|
|
959
|
+
* }
|
|
960
|
+
* ```
|
|
961
|
+
*
|
|
962
|
+
* @example
|
|
963
|
+
* If some of the mutations above can fail independently of the others, and you want to know which ones
|
|
964
|
+
* did — rather than losing that information the moment the first one rejects — swap `Promise.all` for
|
|
965
|
+
* `Promise.allSettled`:
|
|
966
|
+
* ```tsx
|
|
967
|
+
* import { useMutation, useQueryClient } from '@tanstack/solid-query'
|
|
968
|
+
*
|
|
969
|
+
* function AddTodos() {
|
|
970
|
+
* const queryClient = useQueryClient()
|
|
971
|
+
*
|
|
972
|
+
* const addMutation = useMutation(() => ({
|
|
973
|
+
* mutationFn: addTodo,
|
|
974
|
+
* onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
|
|
975
|
+
* }))
|
|
976
|
+
*
|
|
977
|
+
* async function handleAddAll(todos: Array<string>) {
|
|
978
|
+
* const addResults = await Promise.allSettled(
|
|
979
|
+
* todos.map((todo) => addMutation.mutateAsync(todo)),
|
|
980
|
+
* )
|
|
981
|
+
*
|
|
982
|
+
* addResults.forEach((addResult, index) => {
|
|
983
|
+
* if (addResult.status === 'rejected') {
|
|
984
|
+
* console.error(`Failed to add "${todos[index]}":`, addResult.reason)
|
|
985
|
+
* }
|
|
986
|
+
* })
|
|
987
|
+
* }
|
|
988
|
+
*
|
|
989
|
+
* return (
|
|
990
|
+
* <button onClick={() => handleAddAll(['Todo 1', 'Todo 2', 'Todo 3'])}>
|
|
991
|
+
* Add all
|
|
992
|
+
* </button>
|
|
993
|
+
* )
|
|
994
|
+
* }
|
|
995
|
+
* ```
|
|
996
|
+
*/
|
|
114
997
|
declare function useMutation<TData = unknown, TError = DefaultError, TVariables = void, TOnMutateResult = unknown>(options: UseMutationOptions<TData, TError, TVariables, TOnMutateResult>, queryClient?: Accessor<QueryClient>): UseMutationResult<TData, TError, TVariables, TOnMutateResult>;
|
|
115
998
|
//#endregion
|
|
116
999
|
//#region src/useQueries.d.ts
|
|
@@ -164,28 +1047,254 @@ type QueriesOptions<T extends Array<any>, TResult extends Array<any> = [], TDept
|
|
|
164
1047
|
* QueriesResults reducer recursively maps type param to results
|
|
165
1048
|
*/
|
|
166
1049
|
type QueriesResults<T extends Array<any>, TResult extends Array<any> = [], TDepth extends ReadonlyArray<number> = []> = TDepth['length'] extends MAXIMUM_DEPTH ? Array<UseQueryResult> : T extends [] ? [] : T extends [infer Head] ? [...TResult, GetResults<Head>] : T extends [infer Head, ...infer Tail] ? QueriesResults<[...Tail], [...TResult, GetResults<Head>], [...TDepth, 1]> : { [K in keyof T]: GetResults<T[K]>; };
|
|
1050
|
+
/**
|
|
1051
|
+
* The `useQueries` hook can be used to fetch a variable number of queries.
|
|
1052
|
+
*
|
|
1053
|
+
* The `queries` key accepts an array with query option objects mostly identical to `useQuery` — see
|
|
1054
|
+
* `placeholderData` below for the one difference. A custom `QueryClient` is supplied once, as `useQueries`'
|
|
1055
|
+
* own top-level second argument, rather than per query.
|
|
1056
|
+
*
|
|
1057
|
+
* Having the same query key more than once in the array of query objects may cause some data to be shared
|
|
1058
|
+
* between queries. To avoid this, consider de-duplicating the queries and map the results back to the desired
|
|
1059
|
+
* structure.
|
|
1060
|
+
*
|
|
1061
|
+
* The `combine` option can be used to combine the results of the queries into a single value. The result will
|
|
1062
|
+
* be structurally shared to be as referentially stable as possible.
|
|
1063
|
+
*
|
|
1064
|
+
* `placeholderData` is supported here too, but unlike `useQuery`, it doesn't receive information from
|
|
1065
|
+
* previously rendered queries, because the number of queries can differ between renders.
|
|
1066
|
+
* @param queriesOptions - An accessor returning the `queries` array to run, and an optional `combine`
|
|
1067
|
+
* function.
|
|
1068
|
+
* @param queryClient - An accessor for a custom `QueryClient`. Otherwise, the one from the nearest context
|
|
1069
|
+
* will be used.
|
|
1070
|
+
* @returns The combined result. Without `combine`, this is an array with all the query results, in the same
|
|
1071
|
+
* order as the input. When `combine` is provided, this is the value returned by `combine` instead.
|
|
1072
|
+
*
|
|
1073
|
+
* @example
|
|
1074
|
+
* ```tsx
|
|
1075
|
+
* import { For } from 'solid-js'
|
|
1076
|
+
* import { useQueries } from '@tanstack/solid-query'
|
|
1077
|
+
*
|
|
1078
|
+
* function Posts(props: { ids: Array<number> }) {
|
|
1079
|
+
* const postQueries = useQueries(() => ({
|
|
1080
|
+
* queries: props.ids.map((id) => ({
|
|
1081
|
+
* queryKey: ['post', id],
|
|
1082
|
+
* queryFn: () => fetchPost(id),
|
|
1083
|
+
* staleTime: Infinity,
|
|
1084
|
+
* })),
|
|
1085
|
+
* }))
|
|
1086
|
+
*
|
|
1087
|
+
* return (
|
|
1088
|
+
* <ul>
|
|
1089
|
+
* <For each={postQueries}>
|
|
1090
|
+
* {(postQuery) => {
|
|
1091
|
+
* if (postQuery.isPending) return <li>Loading...</li>
|
|
1092
|
+
* if (postQuery.isError) return <li>Error: {postQuery.error.message}</li>
|
|
1093
|
+
* return <li>{postQuery.data.title}</li>
|
|
1094
|
+
* }}
|
|
1095
|
+
* </For>
|
|
1096
|
+
* </ul>
|
|
1097
|
+
* )
|
|
1098
|
+
* }
|
|
1099
|
+
* ```
|
|
1100
|
+
*
|
|
1101
|
+
* @example
|
|
1102
|
+
* Combining results into a single value:
|
|
1103
|
+
* ```tsx
|
|
1104
|
+
* import { For, Match, Switch } from 'solid-js'
|
|
1105
|
+
* import { useQueries } from '@tanstack/solid-query'
|
|
1106
|
+
*
|
|
1107
|
+
* function Posts(props: { ids: Array<number> }) {
|
|
1108
|
+
* const combinedPostsQuery = useQueries(() => ({
|
|
1109
|
+
* queries: props.ids.map((id) => ({
|
|
1110
|
+
* queryKey: ['post', id],
|
|
1111
|
+
* queryFn: () => fetchPost(id),
|
|
1112
|
+
* })),
|
|
1113
|
+
* combine: (postQueries) => {
|
|
1114
|
+
* return {
|
|
1115
|
+
* data: postQueries.map((postQuery) => postQuery.data),
|
|
1116
|
+
* isPending: postQueries.some((postQuery) => postQuery.isPending),
|
|
1117
|
+
* isError: postQueries.some((postQuery) => postQuery.isError),
|
|
1118
|
+
* }
|
|
1119
|
+
* },
|
|
1120
|
+
* }))
|
|
1121
|
+
*
|
|
1122
|
+
* return (
|
|
1123
|
+
* <Switch
|
|
1124
|
+
* fallback={
|
|
1125
|
+
* <ul>
|
|
1126
|
+
* <For each={combinedPostsQuery.data}>{(post) => <li>{post?.title}</li>}</For>
|
|
1127
|
+
* </ul>
|
|
1128
|
+
* }
|
|
1129
|
+
* >
|
|
1130
|
+
* <Match when={combinedPostsQuery.isPending}>Loading...</Match>
|
|
1131
|
+
* <Match when={combinedPostsQuery.isError}>Error loading posts</Match>
|
|
1132
|
+
* </Switch>
|
|
1133
|
+
* )
|
|
1134
|
+
* }
|
|
1135
|
+
* ```
|
|
1136
|
+
*/
|
|
167
1137
|
declare function useQueries<T extends Array<any>, TCombinedResult extends QueriesResults<T> = QueriesResults<T>>(queriesOptions: Accessor<{
|
|
168
1138
|
queries: readonly [...QueriesOptions<T>] | readonly [...{ [K in keyof T]: GetOptions<T[K]>; }];
|
|
169
1139
|
combine?: (result: QueriesResults<T>) => TCombinedResult;
|
|
170
1140
|
}>, queryClient?: Accessor<QueryClient>): TCombinedResult;
|
|
171
1141
|
//#endregion
|
|
172
1142
|
//#region src/QueryClientProvider.d.ts
|
|
1143
|
+
/**
|
|
1144
|
+
* The context that `useQueryClient` reads from. `QueryClientProvider` is the normal way to set it.
|
|
1145
|
+
*/
|
|
173
1146
|
declare const QueryClientContext: import("solid-js").Context<(() => QueryClient) | undefined>;
|
|
1147
|
+
/**
|
|
1148
|
+
* The `useQueryClient` hook returns the current `QueryClient` instance.
|
|
1149
|
+
*
|
|
1150
|
+
* @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will
|
|
1151
|
+
* be used.
|
|
1152
|
+
* @returns The current `QueryClient` instance.
|
|
1153
|
+
* @throws If no `queryClient` argument is passed and no `QueryClientProvider` is found in the component tree.
|
|
1154
|
+
*/
|
|
174
1155
|
declare const useQueryClient: (queryClient?: QueryClient) => QueryClient;
|
|
1156
|
+
/**
|
|
1157
|
+
* The props accepted by `QueryClientProvider`.
|
|
1158
|
+
*/
|
|
175
1159
|
type QueryClientProviderProps = {
|
|
1160
|
+
/**
|
|
1161
|
+
* **Required**
|
|
1162
|
+
*
|
|
1163
|
+
* The `QueryClient` instance to provide.
|
|
1164
|
+
*/
|
|
176
1165
|
client: QueryClient;
|
|
1166
|
+
/**
|
|
1167
|
+
* The components that get access to the provided `QueryClient`.
|
|
1168
|
+
*/
|
|
177
1169
|
children?: JSX.Element;
|
|
178
1170
|
};
|
|
1171
|
+
/**
|
|
1172
|
+
* Use the `QueryClientProvider` component to connect and provide a `QueryClient` to your application. Also
|
|
1173
|
+
* calls `client.mount()`/`client.unmount()` as this component mounts/unmounts, which subscribes the client to
|
|
1174
|
+
* focus/online events (resuming any paused mutations and refetching as needed when the app regains focus or
|
|
1175
|
+
* comes back online).
|
|
1176
|
+
*
|
|
1177
|
+
* @returns The provided `children`, wrapped so they can read the `QueryClient` via `useQueryClient`.
|
|
1178
|
+
*
|
|
1179
|
+
* @example
|
|
1180
|
+
* ```tsx
|
|
1181
|
+
* import { QueryClient, QueryClientProvider } from '@tanstack/solid-query'
|
|
1182
|
+
*
|
|
1183
|
+
* const queryClient = new QueryClient()
|
|
1184
|
+
*
|
|
1185
|
+
* function App() {
|
|
1186
|
+
* return <QueryClientProvider client={queryClient}>...</QueryClientProvider>
|
|
1187
|
+
* }
|
|
1188
|
+
* ```
|
|
1189
|
+
*/
|
|
179
1190
|
declare const QueryClientProvider: (props: QueryClientProviderProps) => JSX.Element;
|
|
180
1191
|
//#endregion
|
|
181
1192
|
//#region src/useIsFetching.d.ts
|
|
1193
|
+
/**
|
|
1194
|
+
* The `useIsFetching` hook returns the `number` of the queries that your application is loading or fetching
|
|
1195
|
+
* in the background (useful for app-wide loading indicators).
|
|
1196
|
+
*
|
|
1197
|
+
* @param filters - An accessor returning the {@link QueryFilters} to narrow down the matched queries.
|
|
1198
|
+
* @param queryClient - An accessor for a custom `QueryClient`. Otherwise, the one from the nearest context
|
|
1199
|
+
* will be used.
|
|
1200
|
+
* @returns An accessor for the `number` of the queries that your application is currently loading or fetching
|
|
1201
|
+
* in the background.
|
|
1202
|
+
*
|
|
1203
|
+
* @example
|
|
1204
|
+
* ```tsx
|
|
1205
|
+
* import { useIsFetching } from '@tanstack/solid-query'
|
|
1206
|
+
*
|
|
1207
|
+
* function GlobalLoadingIndicator() {
|
|
1208
|
+
* // How many queries matching the posts prefix are fetching?
|
|
1209
|
+
* const isFetchingPosts = useIsFetching(() => ({ queryKey: ['posts'] }))
|
|
1210
|
+
*
|
|
1211
|
+
* return isFetchingPosts() > 0 ? <span>Loading posts...</span> : null
|
|
1212
|
+
* }
|
|
1213
|
+
* ```
|
|
1214
|
+
*/
|
|
182
1215
|
declare function useIsFetching(filters?: Accessor<QueryFilters>, queryClient?: Accessor<QueryClient>): Accessor<number>;
|
|
183
1216
|
//#endregion
|
|
184
1217
|
//#region src/mutationOptions.d.ts
|
|
1218
|
+
/**
|
|
1219
|
+
* You can generally pass everything to `mutationOptions` that you can also pass to `useMutation`. A
|
|
1220
|
+
* `mutationKey` is required on this overload so the mutation can be looked up later, e.g. with
|
|
1221
|
+
* `useMutationState`.
|
|
1222
|
+
*
|
|
1223
|
+
* @see {@link useMutation} to run the mutation these options describe.
|
|
1224
|
+
* @param options - The mutation options to use, identical to what you'd pass to `useMutation`, with a
|
|
1225
|
+
* required `mutationKey`.
|
|
1226
|
+
* @returns The same options object, unchanged.
|
|
1227
|
+
*
|
|
1228
|
+
* @example
|
|
1229
|
+
* Looking the mutation up elsewhere via its `mutationKey`, e.g. for a global "saving…" indicator:
|
|
1230
|
+
* ```tsx
|
|
1231
|
+
* import { mutationOptions, useMutationState } from '@tanstack/solid-query'
|
|
1232
|
+
*
|
|
1233
|
+
* const createPostOptions = mutationOptions({
|
|
1234
|
+
* mutationKey: ['posts', 'create'],
|
|
1235
|
+
* mutationFn: createPost,
|
|
1236
|
+
* })
|
|
1237
|
+
*
|
|
1238
|
+
* function SavingIndicator() {
|
|
1239
|
+
* const isCreatingPost = useMutationState(() => ({
|
|
1240
|
+
* filters: { mutationKey: createPostOptions.mutationKey, status: 'pending' },
|
|
1241
|
+
* }))
|
|
1242
|
+
*
|
|
1243
|
+
* return isCreatingPost().length > 0 ? <span>Saving…</span> : null
|
|
1244
|
+
* }
|
|
1245
|
+
* ```
|
|
1246
|
+
*/
|
|
185
1247
|
declare function mutationOptions<TData = unknown, TError = DefaultError, TVariables = void, TOnMutateResult = unknown>(options: WithRequired<MutationOptions<TData, TError, TVariables, TOnMutateResult>, 'mutationKey'>): WithRequired<MutationOptions<TData, TError, TVariables, TOnMutateResult>, 'mutationKey'>;
|
|
1248
|
+
/**
|
|
1249
|
+
* You can generally pass everything to `mutationOptions` that you can also pass to `useMutation`. No
|
|
1250
|
+
* `mutationKey` is required on this overload — use this when you don't need to target the mutation via a
|
|
1251
|
+
* `mutationKey` filter later (e.g. with `useMutationState`); it can still be observed through other filters,
|
|
1252
|
+
* such as `status`.
|
|
1253
|
+
*
|
|
1254
|
+
* @see {@link useMutation} to run the mutation these options describe.
|
|
1255
|
+
* @param options - The mutation options to use, identical to what you'd pass to `useMutation`, without a
|
|
1256
|
+
* `mutationKey`.
|
|
1257
|
+
* @returns The same options object, unchanged.
|
|
1258
|
+
* @remarks See the other overload's example for looking a mutation up via `useMutationState`.
|
|
1259
|
+
*
|
|
1260
|
+
* @example
|
|
1261
|
+
* ```tsx
|
|
1262
|
+
* import { mutationOptions, useMutation } from '@tanstack/solid-query'
|
|
1263
|
+
*
|
|
1264
|
+
* const createPostOptions = mutationOptions({
|
|
1265
|
+
* mutationFn: createPost,
|
|
1266
|
+
* })
|
|
1267
|
+
*
|
|
1268
|
+
* function CreatePost() {
|
|
1269
|
+
* const createPostMutation = useMutation(() => createPostOptions)
|
|
1270
|
+
* return <button onClick={() => createPostMutation.mutate({ title: 'Hello' })}>Create</button>
|
|
1271
|
+
* }
|
|
1272
|
+
* ```
|
|
1273
|
+
*/
|
|
186
1274
|
declare function mutationOptions<TData = unknown, TError = DefaultError, TVariables = void, TOnMutateResult = unknown>(options: Omit<MutationOptions<TData, TError, TVariables, TOnMutateResult>, 'mutationKey'>): Omit<MutationOptions<TData, TError, TVariables, TOnMutateResult>, 'mutationKey'>;
|
|
187
1275
|
//#endregion
|
|
188
1276
|
//#region src/useIsMutating.d.ts
|
|
1277
|
+
/**
|
|
1278
|
+
* The `useIsMutating` hook returns the `number` of mutations that your application currently has `pending`
|
|
1279
|
+
* (useful for app-wide loading indicators).
|
|
1280
|
+
*
|
|
1281
|
+
* @param filters - An accessor returning the {@link MutationFilters} to narrow down the matched mutations.
|
|
1282
|
+
* @param queryClient - An accessor for a custom `QueryClient`. Otherwise, the one from the nearest context
|
|
1283
|
+
* will be used.
|
|
1284
|
+
* @returns An accessor for the `number` of the mutations that your application currently has `pending`.
|
|
1285
|
+
*
|
|
1286
|
+
* @example
|
|
1287
|
+
* ```tsx
|
|
1288
|
+
* import { useIsMutating } from '@tanstack/solid-query'
|
|
1289
|
+
*
|
|
1290
|
+
* function PostsMutatingIndicator() {
|
|
1291
|
+
* // How many mutations matching the posts prefix are in progress?
|
|
1292
|
+
* const isMutatingPosts = useIsMutating(() => ({ mutationKey: ['posts'] }))
|
|
1293
|
+
*
|
|
1294
|
+
* return isMutatingPosts() > 0 ? <span>Saving posts...</span> : null
|
|
1295
|
+
* }
|
|
1296
|
+
* ```
|
|
1297
|
+
*/
|
|
189
1298
|
declare function useIsMutating(filters?: Accessor<MutationFilters>, queryClient?: Accessor<QueryClient>): Accessor<number>;
|
|
190
1299
|
//#endregion
|
|
191
1300
|
//#region src/useMutationState.d.ts
|
|
@@ -194,10 +1303,94 @@ type MutationStateOptions<TResult = MutationState, TMutation extends Mutation<an
|
|
|
194
1303
|
filters?: MutationFilters;
|
|
195
1304
|
select?: (mutation: TMutation) => TResult;
|
|
196
1305
|
};
|
|
1306
|
+
/**
|
|
1307
|
+
* `useMutationState` is a hook that gives you access to all mutations in the `MutationCache`. You can pass
|
|
1308
|
+
* `filters` ({@link MutationFilters}) to narrow down your mutations, and `select` to transform the mutation
|
|
1309
|
+
* state.
|
|
1310
|
+
*
|
|
1311
|
+
* @param options - An accessor returning the `filters` to narrow down matched mutations, and an optional
|
|
1312
|
+
* `select` to transform the mutation state.
|
|
1313
|
+
* @param queryClient - An accessor for a custom `QueryClient`. Otherwise, the one from the nearest context
|
|
1314
|
+
* will be used.
|
|
1315
|
+
* @returns An accessor for an array of whatever `select` returns for each matching mutation.
|
|
1316
|
+
*
|
|
1317
|
+
* @example
|
|
1318
|
+
* Get all variables of all running mutations:
|
|
1319
|
+
* ```tsx
|
|
1320
|
+
* import { useMutationState } from '@tanstack/solid-query'
|
|
1321
|
+
*
|
|
1322
|
+
* function PendingPosts() {
|
|
1323
|
+
* const pendingVariables = useMutationState(() => ({
|
|
1324
|
+
* filters: { status: 'pending' },
|
|
1325
|
+
* select: (mutation) => mutation.state.variables,
|
|
1326
|
+
* }))
|
|
1327
|
+
*
|
|
1328
|
+
* return <>{pendingVariables().length} posts saving...</>
|
|
1329
|
+
* }
|
|
1330
|
+
* ```
|
|
1331
|
+
*
|
|
1332
|
+
* @example
|
|
1333
|
+
* Get all data for specific mutations via the `mutationKey`:
|
|
1334
|
+
* ```tsx
|
|
1335
|
+
* import { useMutation, useMutationState } from '@tanstack/solid-query'
|
|
1336
|
+
*
|
|
1337
|
+
* const mutationKey = ['posts']
|
|
1338
|
+
*
|
|
1339
|
+
* function Posts() {
|
|
1340
|
+
* // Some mutation that we want to get the state for
|
|
1341
|
+
* const createPostsMutation = useMutation(() => ({
|
|
1342
|
+
* mutationKey,
|
|
1343
|
+
* mutationFn: createPosts,
|
|
1344
|
+
* }))
|
|
1345
|
+
*
|
|
1346
|
+
* const savedPosts = useMutationState(() => ({
|
|
1347
|
+
* // this mutation key needs to match the mutation key of the given mutation (see above)
|
|
1348
|
+
* filters: { mutationKey, status: 'success' },
|
|
1349
|
+
* select: (mutation) => mutation.state.data,
|
|
1350
|
+
* }))
|
|
1351
|
+
*
|
|
1352
|
+
* return (
|
|
1353
|
+
* <button onClick={() => createPostsMutation.mutate(['New Post'])}>
|
|
1354
|
+
* Create post ({savedPosts().length} saved so far)
|
|
1355
|
+
* </button>
|
|
1356
|
+
* )
|
|
1357
|
+
* }
|
|
1358
|
+
* ```
|
|
1359
|
+
*
|
|
1360
|
+
* @example
|
|
1361
|
+
* Access the latest successful mutation data via the `mutationKey`. Each invocation of `mutate` adds a new
|
|
1362
|
+
* entry to the mutation cache for `gcTime` milliseconds — with the `status: 'success'` filter below, check the
|
|
1363
|
+
* last item that `useMutationState` returns to get the latest successful invocation:
|
|
1364
|
+
* ```tsx
|
|
1365
|
+
* import { useMutationState } from '@tanstack/solid-query'
|
|
1366
|
+
*
|
|
1367
|
+
* function LatestPost() {
|
|
1368
|
+
* const savedPosts = useMutationState(() => ({
|
|
1369
|
+
* filters: { mutationKey: ['posts'], status: 'success' },
|
|
1370
|
+
* select: (mutation) => mutation.state.data,
|
|
1371
|
+
* }))
|
|
1372
|
+
*
|
|
1373
|
+
* const latestPost = () => savedPosts()[savedPosts().length - 1]
|
|
1374
|
+
*
|
|
1375
|
+
* return <span>{latestPost()?.title}</span>
|
|
1376
|
+
* }
|
|
1377
|
+
* ```
|
|
1378
|
+
*/
|
|
197
1379
|
declare function useMutationState<TResult = MutationState, TMutation extends Mutation<any, any, any, any> = MutationTypeFromResult<TResult>>(options?: Accessor<MutationStateOptions<TResult, TMutation>>, queryClient?: Accessor<QueryClient>): Accessor<Array<TResult>>;
|
|
198
1380
|
//#endregion
|
|
199
1381
|
//#region src/isRestoring.d.ts
|
|
1382
|
+
/**
|
|
1383
|
+
* If you are using `PersistQueryClientProvider`, you can also use the `useIsRestoring` hook alongside it to
|
|
1384
|
+
* check if a restore is currently in progress. `useQuery` and friends also check this internally to avoid
|
|
1385
|
+
* race conditions between the restore and mounting queries.
|
|
1386
|
+
*
|
|
1387
|
+
* @returns An accessor that reads `true` while a persisted client is being restored, `false` otherwise.
|
|
1388
|
+
*/
|
|
200
1389
|
declare const useIsRestoring: () => Accessor<boolean>;
|
|
1390
|
+
/**
|
|
1391
|
+
* The Provider that `PersistQueryClientProvider` uses to signal whether a persisted client is currently
|
|
1392
|
+
* being restored, read by `useIsRestoring`.
|
|
1393
|
+
*/
|
|
201
1394
|
declare const IsRestoringProvider: import("solid-js").ContextProviderComponent<Accessor<boolean>>;
|
|
202
1395
|
//#endregion
|
|
203
1396
|
//#region src/index.d.ts
|