@tanstack/preact-query 5.102.8 → 5.103.1

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.
Files changed (205) hide show
  1. package/build/legacy/HydrationBoundary.cjs +1 -1
  2. package/build/legacy/HydrationBoundary.cjs.map +1 -1
  3. package/build/legacy/HydrationBoundary.js +1 -1
  4. package/build/legacy/HydrationBoundary.js.map +1 -1
  5. package/build/legacy/QueryErrorResetBoundary.cjs +12 -12
  6. package/build/legacy/QueryErrorResetBoundary.cjs.map +1 -1
  7. package/build/legacy/QueryErrorResetBoundary.d.cts +12 -12
  8. package/build/legacy/QueryErrorResetBoundary.d.ts +12 -12
  9. package/build/legacy/QueryErrorResetBoundary.js +12 -12
  10. package/build/legacy/QueryErrorResetBoundary.js.map +1 -1
  11. package/build/legacy/infiniteQueryOptions.cjs.map +1 -1
  12. package/build/legacy/infiniteQueryOptions.d.cts +41 -55
  13. package/build/legacy/infiniteQueryOptions.d.cts.map +1 -1
  14. package/build/legacy/infiniteQueryOptions.d.ts +41 -55
  15. package/build/legacy/infiniteQueryOptions.d.ts.map +1 -1
  16. package/build/legacy/infiniteQueryOptions.js.map +1 -1
  17. package/build/legacy/mutationOptions.cjs.map +1 -1
  18. package/build/legacy/mutationOptions.d.cts +4 -17
  19. package/build/legacy/mutationOptions.d.cts.map +1 -1
  20. package/build/legacy/mutationOptions.d.ts +4 -17
  21. package/build/legacy/mutationOptions.d.ts.map +1 -1
  22. package/build/legacy/mutationOptions.js.map +1 -1
  23. package/build/legacy/queryOptions.cjs.map +1 -1
  24. package/build/legacy/queryOptions.d.cts +51 -74
  25. package/build/legacy/queryOptions.d.cts.map +1 -1
  26. package/build/legacy/queryOptions.d.ts +51 -74
  27. package/build/legacy/queryOptions.d.ts.map +1 -1
  28. package/build/legacy/queryOptions.js.map +1 -1
  29. package/build/legacy/useInfiniteQuery.cjs.map +1 -1
  30. package/build/legacy/useInfiniteQuery.d.cts +208 -36
  31. package/build/legacy/useInfiniteQuery.d.cts.map +1 -1
  32. package/build/legacy/useInfiniteQuery.d.ts +208 -36
  33. package/build/legacy/useInfiniteQuery.d.ts.map +1 -1
  34. package/build/legacy/useInfiniteQuery.js.map +1 -1
  35. package/build/legacy/useIsFetching.cjs +8 -6
  36. package/build/legacy/useIsFetching.cjs.map +1 -1
  37. package/build/legacy/useIsFetching.d.cts +8 -6
  38. package/build/legacy/useIsFetching.d.cts.map +1 -1
  39. package/build/legacy/useIsFetching.d.ts +8 -6
  40. package/build/legacy/useIsFetching.d.ts.map +1 -1
  41. package/build/legacy/useIsFetching.js +8 -6
  42. package/build/legacy/useIsFetching.js.map +1 -1
  43. package/build/legacy/useMutation.cjs +13 -11
  44. package/build/legacy/useMutation.cjs.map +1 -1
  45. package/build/legacy/useMutation.d.cts +13 -11
  46. package/build/legacy/useMutation.d.cts.map +1 -1
  47. package/build/legacy/useMutation.d.ts +13 -11
  48. package/build/legacy/useMutation.d.ts.map +1 -1
  49. package/build/legacy/useMutation.js +13 -11
  50. package/build/legacy/useMutation.js.map +1 -1
  51. package/build/legacy/useMutationState.cjs +49 -29
  52. package/build/legacy/useMutationState.cjs.map +1 -1
  53. package/build/legacy/useMutationState.d.cts +49 -29
  54. package/build/legacy/useMutationState.d.cts.map +1 -1
  55. package/build/legacy/useMutationState.d.ts +49 -29
  56. package/build/legacy/useMutationState.d.ts.map +1 -1
  57. package/build/legacy/useMutationState.js +49 -29
  58. package/build/legacy/useMutationState.js.map +1 -1
  59. package/build/legacy/useQueries.cjs +50 -23
  60. package/build/legacy/useQueries.cjs.map +1 -1
  61. package/build/legacy/useQueries.d.cts +50 -23
  62. package/build/legacy/useQueries.d.cts.map +1 -1
  63. package/build/legacy/useQueries.d.ts +50 -23
  64. package/build/legacy/useQueries.d.ts.map +1 -1
  65. package/build/legacy/useQueries.js +50 -23
  66. package/build/legacy/useQueries.js.map +1 -1
  67. package/build/legacy/useQuery.cjs.map +1 -1
  68. package/build/legacy/useQuery.d.cts +93 -33
  69. package/build/legacy/useQuery.d.cts.map +1 -1
  70. package/build/legacy/useQuery.d.ts +93 -33
  71. package/build/legacy/useQuery.d.ts.map +1 -1
  72. package/build/legacy/useQuery.js.map +1 -1
  73. package/build/legacy/useSuspenseInfiniteQuery.cjs +57 -7
  74. package/build/legacy/useSuspenseInfiniteQuery.cjs.map +1 -1
  75. package/build/legacy/useSuspenseInfiniteQuery.d.cts +57 -7
  76. package/build/legacy/useSuspenseInfiniteQuery.d.cts.map +1 -1
  77. package/build/legacy/useSuspenseInfiniteQuery.d.ts +57 -7
  78. package/build/legacy/useSuspenseInfiniteQuery.d.ts.map +1 -1
  79. package/build/legacy/useSuspenseInfiniteQuery.js +57 -7
  80. package/build/legacy/useSuspenseInfiniteQuery.js.map +1 -1
  81. package/build/legacy/useSuspenseQueries.cjs.map +1 -1
  82. package/build/legacy/useSuspenseQueries.d.cts +244 -20
  83. package/build/legacy/useSuspenseQueries.d.cts.map +1 -1
  84. package/build/legacy/useSuspenseQueries.d.ts +244 -20
  85. package/build/legacy/useSuspenseQueries.d.ts.map +1 -1
  86. package/build/legacy/useSuspenseQueries.js.map +1 -1
  87. package/build/legacy/useSuspenseQuery.cjs +48 -8
  88. package/build/legacy/useSuspenseQuery.cjs.map +1 -1
  89. package/build/legacy/useSuspenseQuery.d.cts +48 -8
  90. package/build/legacy/useSuspenseQuery.d.cts.map +1 -1
  91. package/build/legacy/useSuspenseQuery.d.ts +48 -8
  92. package/build/legacy/useSuspenseQuery.d.ts.map +1 -1
  93. package/build/legacy/useSuspenseQuery.js +48 -8
  94. package/build/legacy/useSuspenseQuery.js.map +1 -1
  95. package/build/modern/HydrationBoundary.cjs +1 -1
  96. package/build/modern/HydrationBoundary.cjs.map +1 -1
  97. package/build/modern/HydrationBoundary.js +1 -1
  98. package/build/modern/HydrationBoundary.js.map +1 -1
  99. package/build/modern/QueryErrorResetBoundary.cjs +12 -12
  100. package/build/modern/QueryErrorResetBoundary.cjs.map +1 -1
  101. package/build/modern/QueryErrorResetBoundary.d.cts +12 -12
  102. package/build/modern/QueryErrorResetBoundary.d.ts +12 -12
  103. package/build/modern/QueryErrorResetBoundary.js +12 -12
  104. package/build/modern/QueryErrorResetBoundary.js.map +1 -1
  105. package/build/modern/infiniteQueryOptions.cjs.map +1 -1
  106. package/build/modern/infiniteQueryOptions.d.cts +41 -55
  107. package/build/modern/infiniteQueryOptions.d.cts.map +1 -1
  108. package/build/modern/infiniteQueryOptions.d.ts +41 -55
  109. package/build/modern/infiniteQueryOptions.d.ts.map +1 -1
  110. package/build/modern/infiniteQueryOptions.js.map +1 -1
  111. package/build/modern/mutationOptions.cjs.map +1 -1
  112. package/build/modern/mutationOptions.d.cts +4 -17
  113. package/build/modern/mutationOptions.d.cts.map +1 -1
  114. package/build/modern/mutationOptions.d.ts +4 -17
  115. package/build/modern/mutationOptions.d.ts.map +1 -1
  116. package/build/modern/mutationOptions.js.map +1 -1
  117. package/build/modern/queryOptions.cjs.map +1 -1
  118. package/build/modern/queryOptions.d.cts +51 -74
  119. package/build/modern/queryOptions.d.cts.map +1 -1
  120. package/build/modern/queryOptions.d.ts +51 -74
  121. package/build/modern/queryOptions.d.ts.map +1 -1
  122. package/build/modern/queryOptions.js.map +1 -1
  123. package/build/modern/useInfiniteQuery.cjs.map +1 -1
  124. package/build/modern/useInfiniteQuery.d.cts +208 -36
  125. package/build/modern/useInfiniteQuery.d.cts.map +1 -1
  126. package/build/modern/useInfiniteQuery.d.ts +208 -36
  127. package/build/modern/useInfiniteQuery.d.ts.map +1 -1
  128. package/build/modern/useInfiniteQuery.js.map +1 -1
  129. package/build/modern/useIsFetching.cjs +8 -6
  130. package/build/modern/useIsFetching.cjs.map +1 -1
  131. package/build/modern/useIsFetching.d.cts +8 -6
  132. package/build/modern/useIsFetching.d.cts.map +1 -1
  133. package/build/modern/useIsFetching.d.ts +8 -6
  134. package/build/modern/useIsFetching.d.ts.map +1 -1
  135. package/build/modern/useIsFetching.js +8 -6
  136. package/build/modern/useIsFetching.js.map +1 -1
  137. package/build/modern/useMutation.cjs +13 -11
  138. package/build/modern/useMutation.cjs.map +1 -1
  139. package/build/modern/useMutation.d.cts +13 -11
  140. package/build/modern/useMutation.d.cts.map +1 -1
  141. package/build/modern/useMutation.d.ts +13 -11
  142. package/build/modern/useMutation.d.ts.map +1 -1
  143. package/build/modern/useMutation.js +13 -11
  144. package/build/modern/useMutation.js.map +1 -1
  145. package/build/modern/useMutationState.cjs +49 -29
  146. package/build/modern/useMutationState.cjs.map +1 -1
  147. package/build/modern/useMutationState.d.cts +49 -29
  148. package/build/modern/useMutationState.d.cts.map +1 -1
  149. package/build/modern/useMutationState.d.ts +49 -29
  150. package/build/modern/useMutationState.d.ts.map +1 -1
  151. package/build/modern/useMutationState.js +49 -29
  152. package/build/modern/useMutationState.js.map +1 -1
  153. package/build/modern/useQueries.cjs +50 -23
  154. package/build/modern/useQueries.cjs.map +1 -1
  155. package/build/modern/useQueries.d.cts +50 -23
  156. package/build/modern/useQueries.d.cts.map +1 -1
  157. package/build/modern/useQueries.d.ts +50 -23
  158. package/build/modern/useQueries.d.ts.map +1 -1
  159. package/build/modern/useQueries.js +50 -23
  160. package/build/modern/useQueries.js.map +1 -1
  161. package/build/modern/useQuery.cjs.map +1 -1
  162. package/build/modern/useQuery.d.cts +93 -33
  163. package/build/modern/useQuery.d.cts.map +1 -1
  164. package/build/modern/useQuery.d.ts +93 -33
  165. package/build/modern/useQuery.d.ts.map +1 -1
  166. package/build/modern/useQuery.js.map +1 -1
  167. package/build/modern/useSuspenseInfiniteQuery.cjs +57 -7
  168. package/build/modern/useSuspenseInfiniteQuery.cjs.map +1 -1
  169. package/build/modern/useSuspenseInfiniteQuery.d.cts +57 -7
  170. package/build/modern/useSuspenseInfiniteQuery.d.cts.map +1 -1
  171. package/build/modern/useSuspenseInfiniteQuery.d.ts +57 -7
  172. package/build/modern/useSuspenseInfiniteQuery.d.ts.map +1 -1
  173. package/build/modern/useSuspenseInfiniteQuery.js +57 -7
  174. package/build/modern/useSuspenseInfiniteQuery.js.map +1 -1
  175. package/build/modern/useSuspenseQueries.cjs.map +1 -1
  176. package/build/modern/useSuspenseQueries.d.cts +244 -20
  177. package/build/modern/useSuspenseQueries.d.cts.map +1 -1
  178. package/build/modern/useSuspenseQueries.d.ts +244 -20
  179. package/build/modern/useSuspenseQueries.d.ts.map +1 -1
  180. package/build/modern/useSuspenseQueries.js.map +1 -1
  181. package/build/modern/useSuspenseQuery.cjs +48 -8
  182. package/build/modern/useSuspenseQuery.cjs.map +1 -1
  183. package/build/modern/useSuspenseQuery.d.cts +48 -8
  184. package/build/modern/useSuspenseQuery.d.cts.map +1 -1
  185. package/build/modern/useSuspenseQuery.d.ts +48 -8
  186. package/build/modern/useSuspenseQuery.d.ts.map +1 -1
  187. package/build/modern/useSuspenseQuery.js +48 -8
  188. package/build/modern/useSuspenseQuery.js.map +1 -1
  189. package/build/query-codemods/eslint.config.js +7 -0
  190. package/build/query-codemods/root.eslint.config.js +45 -0
  191. package/package.json +11 -11
  192. package/src/HydrationBoundary.tsx +0 -1
  193. package/src/QueryErrorResetBoundary.tsx +12 -12
  194. package/src/infiniteQueryOptions.ts +41 -55
  195. package/src/mutationOptions.ts +4 -17
  196. package/src/queryOptions.ts +50 -73
  197. package/src/useInfiniteQuery.ts +208 -36
  198. package/src/useIsFetching.ts +8 -6
  199. package/src/useMutation.ts +13 -11
  200. package/src/useMutationState.ts +49 -29
  201. package/src/useQueries.ts +50 -23
  202. package/src/useQuery.ts +93 -33
  203. package/src/useSuspenseInfiniteQuery.ts +57 -7
  204. package/src/useSuspenseQueries.ts +244 -20
  205. package/src/useSuspenseQuery.ts +48 -8
@@ -59,7 +59,9 @@ export type UnusedSkipTokenOptions<
59
59
  > & {
60
60
  /**
61
61
  * `skipToken` is not allowed as a value here — this overload is selected when no `initialData` is set. If
62
- * you don't intend to run the query yet, omit `queryFn` or use a default query function instead.
62
+ * you don't intend to run the query yet, set `enabled: false` — omitting `queryFn` alone still triggers a
63
+ * fetch that fails with "Missing queryFn" unless `enabled` is `false` or a default query function has been
64
+ * defined. A default query function only supplies `queryFn`; it doesn't defer the fetch on its own.
63
65
  */
64
66
  queryFn?: Exclude<
65
67
  UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>['queryFn'],
@@ -108,6 +110,7 @@ export type DefinedInitialDataOptions<
108
110
  * This overload is selected when `initialData` is set, so the resulting `data` is never `undefined`.
109
111
  *
110
112
  * @see {@link useQuery} to run a query with these options.
113
+ * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern.
111
114
  * @param options - The {@link DefinedInitialDataOptions} to use — everything you can pass to `useQuery`, with `initialData` set.
112
115
  * @returns The same options object, typed so that `queryKey` carries the inferred data type.
113
116
  *
@@ -122,9 +125,18 @@ export type DefinedInitialDataOptions<
122
125
  * })
123
126
  *
124
127
  * function Posts() {
125
- * // `data` is `Post[]`, never `undefined`, thanks to `initialData`.
126
- * const { data } = useQuery(postsOptions)
127
- * return <>{data.map((post) => <p key={post.id}>{post.title}</p>)}</>
128
+ * // `data` is `Post[]`, never `undefined`, thanks to `initialData` — even if a refetch fails,
129
+ * // so the list stays visible alongside the error.
130
+ * const { data, isError, error } = useQuery(postsOptions)
131
+ *
132
+ * return (
133
+ * <div>
134
+ * {isError ? <span>Error: {error.message}</span> : null}
135
+ * <ul>
136
+ * {data.map((post) => <li key={post.id}>{post.title}</li>)}
137
+ * </ul>
138
+ * </div>
139
+ * )
128
140
  * }
129
141
  * ```
130
142
  */
@@ -144,23 +156,14 @@ export function queryOptions<
144
156
  * is the query key to generate options for.
145
157
  *
146
158
  * @see {@link useQuery} to run a query with these options.
159
+ * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern.
147
160
  * @param options - The {@link UnusedSkipTokenOptions} to use — everything you can pass to `useQuery`.
148
161
  * @returns The same options object, typed so that `queryKey` carries the inferred data type.
149
162
  *
150
163
  * @example
164
+ * A parameterized factory, so the same options object can be reused per `id`:
151
165
  * ```tsx
152
- * import { queryOptions } from '@tanstack/preact-query'
153
- *
154
- * export const postsOptions = queryOptions({
155
- * queryKey: ['posts'],
156
- * queryFn: fetchPosts,
157
- * })
158
- * ```
159
- *
160
- * @example
161
- * A parameterized factory, reused across a hook and an imperative call with the same cache entry:
162
- * ```tsx
163
- * import { noop, queryOptions, useQuery } from '@tanstack/preact-query'
166
+ * import { queryOptions, useQuery } from '@tanstack/preact-query'
164
167
  *
165
168
  * export const postOptions = (id: string) =>
166
169
  * queryOptions({
@@ -169,33 +172,13 @@ export function queryOptions<
169
172
  * })
170
173
  *
171
174
  * function Post({ id }: { id: string }) {
172
- * const { data } = useQuery(postOptions(id))
173
- * return <h1>{data?.title}</h1>
174
- * }
175
- *
176
- * // Elsewhere, e.g. to warm the cache before rendering `<Post>`:
177
- * queryClient.query(postOptions(id)).catch(noop)
178
- * ```
179
- *
180
- * @example
181
- * The same options object works with every API that accepts query options:
182
- * ```tsx
183
- * import {
184
- * noop,
185
- * queryOptions,
186
- * useQuery,
187
- * useSuspenseQuery,
188
- * } from '@tanstack/preact-query'
175
+ * const { data, isPending, isError, error } = useQuery(postOptions(id))
189
176
  *
190
- * const todosOptions = queryOptions({
191
- * queryKey: ['todos'],
192
- * queryFn: fetchTodos,
193
- * })
177
+ * if (isPending) return 'Loading...'
178
+ * if (isError) return <span>Error: {error.message}</span>
194
179
  *
195
- * useQuery(todosOptions)
196
- * useSuspenseQuery(todosOptions)
197
- * queryClient.query(todosOptions).catch(noop)
198
- * queryClient.getQueryData(todosOptions.queryKey) // typed as Array<Todo> | undefined
180
+ * return <h1>{data.title}</h1>
181
+ * }
199
182
  * ```
200
183
  */
201
184
  export function queryOptions<
@@ -214,23 +197,15 @@ export function queryOptions<
214
197
  * is the query key to generate options for.
215
198
  *
216
199
  * @see {@link useQuery} to run a query with these options.
200
+ * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern.
217
201
  * @param options - The {@link UndefinedInitialDataOptions} to use — everything you can pass to `useQuery`.
218
202
  * @returns The same options object, typed so that `queryKey` carries the inferred data type.
203
+ * @remarks This is the only overload that accepts `queryFn: skipToken`, shown below.
219
204
  *
220
205
  * @example
206
+ * A parameterized factory, so the same options object can be reused per `id`:
221
207
  * ```tsx
222
- * import { queryOptions } from '@tanstack/preact-query'
223
- *
224
- * export const postsOptions = queryOptions({
225
- * queryKey: ['posts'],
226
- * queryFn: fetchPosts,
227
- * })
228
- * ```
229
- *
230
- * @example
231
- * A parameterized factory, reused across a hook and an imperative call with the same cache entry:
232
- * ```tsx
233
- * import { noop, queryOptions, useQuery } from '@tanstack/preact-query'
208
+ * import { queryOptions, useQuery } from '@tanstack/preact-query'
234
209
  *
235
210
  * export const postOptions = (id: string) =>
236
211
  * queryOptions({
@@ -239,33 +214,35 @@ export function queryOptions<
239
214
  * })
240
215
  *
241
216
  * function Post({ id }: { id: string }) {
242
- * const { data } = useQuery(postOptions(id))
243
- * return <h1>{data?.title}</h1>
244
- * }
217
+ * const { data, isPending, isError, error } = useQuery(postOptions(id))
218
+ *
219
+ * if (isPending) return 'Loading...'
220
+ * if (isError) return <span>Error: {error.message}</span>
245
221
  *
246
- * // Elsewhere, e.g. to warm the cache before rendering `<Post>`:
247
- * queryClient.query(postOptions(id)).catch(noop)
222
+ * return <h1>{data.title}</h1>
223
+ * }
248
224
  * ```
249
225
  *
250
226
  * @example
251
- * The same options object works with every API that accepts query options:
227
+ * A factory that disables the query, type safe, until `postId` is set:
252
228
  * ```tsx
253
- * import {
254
- * noop,
255
- * queryOptions,
256
- * useQuery,
257
- * useSuspenseQuery,
258
- * } from '@tanstack/preact-query'
229
+ * import { queryOptions, skipToken, useQuery } from '@tanstack/preact-query'
259
230
  *
260
- * const todosOptions = queryOptions({
261
- * queryKey: ['todos'],
262
- * queryFn: fetchTodos,
263
- * })
231
+ * export const postOptions = (postId: number | undefined) =>
232
+ * queryOptions({
233
+ * queryKey: ['post', postId],
234
+ * queryFn: postId != null ? () => fetchPost(postId) : skipToken,
235
+ * })
236
+ *
237
+ * function Post({ postId }: { postId: number | undefined }) {
238
+ * const { data, isLoading, isError, error } = useQuery(postOptions(postId))
239
+ *
240
+ * if (postId == null) return 'Select a post'
241
+ * if (isLoading) return 'Loading...'
242
+ * if (isError) return <span>Error: {error.message}</span>
264
243
  *
265
- * useQuery(todosOptions)
266
- * useSuspenseQuery(todosOptions)
267
- * queryClient.query(todosOptions).catch(noop)
268
- * queryClient.getQueryData(todosOptions.queryKey) // typed as Array<Todo> | undefined
244
+ * return <h1>{data?.title}</h1>
245
+ * }
269
246
  * ```
270
247
  */
271
248
  export function queryOptions<
@@ -19,7 +19,7 @@ import type {
19
19
  import { useBaseQuery } from './useBaseQuery'
20
20
 
21
21
  /**
22
- * The options for `useInfiniteQuery` are identical to `useQuery`, with the addition of `queryFn`,
22
+ * The options for `useInfiniteQuery` are identical to `useQuery`, with the addition of
23
23
  * `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, and `maxPages`.
24
24
  *
25
25
  * This overload is selected when `initialData` is set.
@@ -31,16 +31,19 @@ import { useBaseQuery } from './useBaseQuery'
31
31
  * @param options - The {@link DefinedInitialDataInfiniteOptions} to use — everything you can pass to `useInfiniteQuery`, with `initialData` set.
32
32
  * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will
33
33
  * be used.
34
- * @returns The same properties as `useQuery`, with the addition of `data.pages`, `data.pageParams`,
35
- * `fetchNextPage`, `fetchPreviousPage`, `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and
36
- * `isFetchingPreviousPage`.
34
+ * @returns The same properties as `useQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`,
35
+ * `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data.pages` and
36
+ * `data.pageParams` are also added, as long as a `select` doesn't change `TData` away from its default
37
+ * `InfiniteData<TQueryFnData>` shape.
37
38
  *
38
39
  * @example
39
40
  * ```tsx
40
41
  * import { useInfiniteQuery } from '@tanstack/preact-query'
41
42
  *
42
43
  * function Projects() {
43
- * const { data } = useInfiniteQuery({
44
+ * // `data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the
45
+ * // list stays visible alongside the error.
46
+ * const { data, isError, error } = useInfiniteQuery({
44
47
  * queryKey: ['projects'],
45
48
  * queryFn: ({ pageParam }) => fetchProjects(pageParam),
46
49
  * initialPageParam: 0,
@@ -48,7 +51,14 @@ import { useBaseQuery } from './useBaseQuery'
48
51
  * initialData: { pages: [], pageParams: [] },
49
52
  * })
50
53
  *
51
- * return <>{data.pages.map((page) => page.projects.map((p) => <p key={p.id}>{p.name}</p>))}</>
54
+ * return (
55
+ * <div>
56
+ * {isError ? <span>Error: {error.message}</span> : null}
57
+ * <ul>
58
+ * {data.pages.map((page) => page.projects.map((p) => <li key={p.id}>{p.name}</li>))}
59
+ * </ul>
60
+ * </div>
61
+ * )
52
62
  * }
53
63
  * ```
54
64
  */
@@ -70,7 +80,7 @@ export function useInfiniteQuery<
70
80
  ): DefinedUseInfiniteQueryResult<TData, TError>
71
81
 
72
82
  /**
73
- * The options for `useInfiniteQuery` are identical to `useQuery`, with the addition of `queryFn`,
83
+ * The options for `useInfiniteQuery` are identical to `useQuery`, with the addition of
74
84
  * `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, and `maxPages`.
75
85
  *
76
86
  * @remarks Keep in mind that imperative fetch calls, such as `fetchNextPage`, may interfere with the default
@@ -80,16 +90,18 @@ export function useInfiniteQuery<
80
90
  * @param options - The {@link UndefinedInitialDataInfiniteOptions} to use — everything you can pass to `useInfiniteQuery`.
81
91
  * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will
82
92
  * be used.
83
- * @returns The same properties as `useQuery`, with the addition of `data.pages`, `data.pageParams`,
84
- * `fetchNextPage`, `fetchPreviousPage`, `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and
85
- * `isFetchingPreviousPage`.
93
+ * @returns The same properties as `useQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`,
94
+ * `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data.pages` and
95
+ * `data.pageParams` are also added, as long as a `select` doesn't change `TData` away from its default
96
+ * `InfiniteData<TQueryFnData>` shape.
86
97
  *
87
98
  * @example
99
+ * Fetching the next page from a "Load More" button click:
88
100
  * ```tsx
89
101
  * import { useInfiniteQuery } from '@tanstack/preact-query'
90
102
  *
91
103
  * function Projects() {
92
- * const { data, fetchNextPage, hasNextPage, isFetching, isFetchingNextPage } =
104
+ * const { data, isPending, isError, error, fetchNextPage, hasNextPage, isFetching, isFetchingNextPage } =
93
105
  * useInfiniteQuery({
94
106
  * queryKey: ['projects'],
95
107
  * queryFn: ({ pageParam }) => fetchProjects(pageParam),
@@ -97,17 +109,81 @@ export function useInfiniteQuery<
97
109
  * getNextPageParam: (lastPage) => lastPage.nextId,
98
110
  * })
99
111
  *
112
+ * if (isPending) return 'Loading...'
113
+ * if (isError) return <span>Error: {error.message}</span>
114
+ *
100
115
  * return (
101
- * <button
102
- * onClick={() => fetchNextPage()}
103
- * disabled={!hasNextPage || isFetching}
104
- * >
105
- * {isFetchingNextPage
106
- * ? 'Loading more...'
107
- * : hasNextPage
108
- * ? 'Load More'
109
- * : 'Nothing more to load'}
110
- * </button>
116
+ * <>
117
+ * <ul>
118
+ * {data.pages.map((page) =>
119
+ * page.projects.map((project) => <li key={project.id}>{project.name}</li>),
120
+ * )}
121
+ * </ul>
122
+ * <button
123
+ * onClick={() => fetchNextPage()}
124
+ * disabled={!hasNextPage || isFetching}
125
+ * >
126
+ * {isFetchingNextPage
127
+ * ? 'Loading more...'
128
+ * : hasNextPage
129
+ * ? 'Load More'
130
+ * : 'Nothing more to load'}
131
+ * </button>
132
+ * </>
133
+ * )
134
+ * }
135
+ * ```
136
+ *
137
+ * @example
138
+ * Fetching the next page automatically as the user scrolls, using an `IntersectionObserver` on a
139
+ * sentinel element after the list:
140
+ * ```tsx
141
+ * import { useInfiniteQuery } from '@tanstack/preact-query'
142
+ * import { useEffect, useRef } from 'preact/hooks'
143
+ *
144
+ * function Projects() {
145
+ * const {
146
+ * data,
147
+ * isPending,
148
+ * isError,
149
+ * error,
150
+ * fetchNextPage,
151
+ * hasNextPage,
152
+ * isFetching,
153
+ * isFetchingNextPage,
154
+ * } = useInfiniteQuery({
155
+ * queryKey: ['projects'],
156
+ * queryFn: ({ pageParam }) => fetchProjects(pageParam),
157
+ * initialPageParam: 0,
158
+ * getNextPageParam: (lastPage) => lastPage.nextId,
159
+ * })
160
+ *
161
+ * const sentinelRef = useRef<HTMLDivElement>(null)
162
+ *
163
+ * useEffect(() => {
164
+ * const sentinel = sentinelRef.current
165
+ * if (sentinel == null || !hasNextPage || isFetching) return
166
+ *
167
+ * const observer = new IntersectionObserver(([entry]) => {
168
+ * if (entry?.isIntersecting) fetchNextPage()
169
+ * })
170
+ * observer.observe(sentinel)
171
+ *
172
+ * return () => observer.disconnect()
173
+ * }, [hasNextPage, isFetching, fetchNextPage])
174
+ *
175
+ * if (isPending) return 'Loading...'
176
+ * if (isError) return <span>Error: {error.message}</span>
177
+ *
178
+ * return (
179
+ * <>
180
+ * <ul>
181
+ * {data.pages.map((page) =>
182
+ * page.projects.map((project) => <li key={project.id}>{project.name}</li>),
183
+ * )}
184
+ * </ul>
185
+ * <div ref={sentinelRef}>{isFetchingNextPage ? 'Loading more...' : null}</div>
186
+ * </>
111
187
  * )
112
188
  * }
113
189
  * ```
@@ -130,7 +206,7 @@ export function useInfiniteQuery<
130
206
  ): UseInfiniteQueryResult<TData, TError>
131
207
 
132
208
  /**
133
- * The options for `useInfiniteQuery` are identical to `useQuery`, with the addition of `queryFn`,
209
+ * The options for `useInfiniteQuery` are identical to `useQuery`, with the addition of
134
210
  * `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, and `maxPages`.
135
211
  *
136
212
  * @remarks Keep in mind that imperative fetch calls, such as `fetchNextPage`, may interfere with the default
@@ -140,16 +216,18 @@ export function useInfiniteQuery<
140
216
  * @param options - The {@link UseInfiniteQueryOptions} to use — everything you can pass to `useInfiniteQuery`.
141
217
  * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will
142
218
  * be used.
143
- * @returns The same properties as `useQuery`, with the addition of `data.pages`, `data.pageParams`,
144
- * `fetchNextPage`, `fetchPreviousPage`, `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and
145
- * `isFetchingPreviousPage`.
219
+ * @returns The same properties as `useQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`,
220
+ * `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data.pages` and
221
+ * `data.pageParams` are also added, as long as a `select` doesn't change `TData` away from its default
222
+ * `InfiniteData<TQueryFnData>` shape.
146
223
  *
147
224
  * @example
225
+ * Fetching the next page from a "Load More" button click:
148
226
  * ```tsx
149
227
  * import { useInfiniteQuery } from '@tanstack/preact-query'
150
228
  *
151
229
  * function Projects() {
152
- * const { data, fetchNextPage, hasNextPage, isFetching, isFetchingNextPage } =
230
+ * const { data, isPending, isError, error, fetchNextPage, hasNextPage, isFetching, isFetchingNextPage } =
153
231
  * useInfiniteQuery({
154
232
  * queryKey: ['projects'],
155
233
  * queryFn: ({ pageParam }) => fetchProjects(pageParam),
@@ -157,17 +235,111 @@ export function useInfiniteQuery<
157
235
  * getNextPageParam: (lastPage) => lastPage.nextId,
158
236
  * })
159
237
  *
238
+ * if (isPending) return 'Loading...'
239
+ * if (isError) return <span>Error: {error.message}</span>
240
+ *
241
+ * return (
242
+ * <>
243
+ * <ul>
244
+ * {data.pages.map((page) =>
245
+ * page.projects.map((project) => <li key={project.id}>{project.name}</li>),
246
+ * )}
247
+ * </ul>
248
+ * <button
249
+ * onClick={() => fetchNextPage()}
250
+ * disabled={!hasNextPage || isFetching}
251
+ * >
252
+ * {isFetchingNextPage
253
+ * ? 'Loading more...'
254
+ * : hasNextPage
255
+ * ? 'Load More'
256
+ * : 'Nothing more to load'}
257
+ * </button>
258
+ * </>
259
+ * )
260
+ * }
261
+ * ```
262
+ *
263
+ * @example
264
+ * Fetching the next page automatically as the user scrolls, using an `IntersectionObserver` on a
265
+ * sentinel element after the list:
266
+ * ```tsx
267
+ * import { useInfiniteQuery } from '@tanstack/preact-query'
268
+ * import { useEffect, useRef } from 'preact/hooks'
269
+ *
270
+ * function Projects() {
271
+ * const {
272
+ * data,
273
+ * isPending,
274
+ * isError,
275
+ * error,
276
+ * fetchNextPage,
277
+ * hasNextPage,
278
+ * isFetching,
279
+ * isFetchingNextPage,
280
+ * } = useInfiniteQuery({
281
+ * queryKey: ['projects'],
282
+ * queryFn: ({ pageParam }) => fetchProjects(pageParam),
283
+ * initialPageParam: 0,
284
+ * getNextPageParam: (lastPage) => lastPage.nextId,
285
+ * })
286
+ *
287
+ * const sentinelRef = useRef<HTMLDivElement>(null)
288
+ *
289
+ * useEffect(() => {
290
+ * const sentinel = sentinelRef.current
291
+ * if (sentinel == null || !hasNextPage || isFetching) return
292
+ *
293
+ * const observer = new IntersectionObserver(([entry]) => {
294
+ * if (entry?.isIntersecting) fetchNextPage()
295
+ * })
296
+ * observer.observe(sentinel)
297
+ *
298
+ * return () => observer.disconnect()
299
+ * }, [hasNextPage, isFetching, fetchNextPage])
300
+ *
301
+ * if (isPending) return 'Loading...'
302
+ * if (isError) return <span>Error: {error.message}</span>
303
+ *
304
+ * return (
305
+ * <>
306
+ * <ul>
307
+ * {data.pages.map((page) =>
308
+ * page.projects.map((project) => <li key={project.id}>{project.name}</li>),
309
+ * )}
310
+ * </ul>
311
+ * <div ref={sentinelRef}>{isFetchingNextPage ? 'Loading more...' : null}</div>
312
+ * </>
313
+ * )
314
+ * }
315
+ * ```
316
+ *
317
+ * @example
318
+ * A query that's disabled, type safe, until `postId` is set — pass `skipToken` as `queryFn`
319
+ * instead of setting `enabled: false`:
320
+ * ```tsx
321
+ * import { skipToken, useInfiniteQuery } from '@tanstack/preact-query'
322
+ *
323
+ * function Comments({ postId }: { postId: string | undefined }) {
324
+ * // Use `isLoading`, not `isPending`, so the loading state doesn't show while the query is disabled.
325
+ * const { data, isLoading, isError, error } = useInfiniteQuery({
326
+ * queryKey: ['post', postId, 'comments'],
327
+ * queryFn:
328
+ * postId != null
329
+ * ? ({ pageParam }) => fetchComments(postId, pageParam)
330
+ * : skipToken,
331
+ * initialPageParam: 0,
332
+ * getNextPageParam: (lastPage) => lastPage.nextId,
333
+ * })
334
+ *
335
+ * if (postId == null) return 'Select a post'
336
+ * if (isLoading) return 'Loading...'
337
+ * if (isError) return <span>Error: {error.message}</span>
338
+ *
160
339
  * return (
161
- * <button
162
- * onClick={() => fetchNextPage()}
163
- * disabled={!hasNextPage || isFetching}
164
- * >
165
- * {isFetchingNextPage
166
- * ? 'Loading more...'
167
- * : hasNextPage
168
- * ? 'Load More'
169
- * : 'Nothing more to load'}
170
- * </button>
340
+ * <ul>
341
+ * {data?.pages.map((page) => page.comments.map((c) => <li key={c.id}>{c.text}</li>))}
342
+ * </ul>
171
343
  * )
172
344
  * }
173
345
  * ```
@@ -6,8 +6,8 @@ import { useQueryClient } from './QueryClientProvider'
6
6
  import { useSyncExternalStore } from './utils'
7
7
 
8
8
  /**
9
- * `useIsFetching` is an optional hook that returns the `number` of the queries that your application is loading or
10
- * fetching in the background (useful for app-wide loading indicators).
9
+ * The `useIsFetching` hook returns the `number` of the queries that your application is loading or fetching in
10
+ * the background (useful for app-wide loading indicators).
11
11
  *
12
12
  * @param filters - The {@link QueryFilters} to narrow down the matched queries.
13
13
  * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will
@@ -19,10 +19,12 @@ import { useSyncExternalStore } from './utils'
19
19
  * ```tsx
20
20
  * import { useIsFetching } from '@tanstack/preact-query'
21
21
  *
22
- * // How many queries are fetching?
23
- * const isFetching = useIsFetching()
24
- * // How many queries matching the posts prefix are fetching?
25
- * const isFetchingPosts = useIsFetching({ queryKey: ['posts'] })
22
+ * function PostsFetchingIndicator() {
23
+ * // How many queries matching the posts prefix are fetching?
24
+ * const isFetchingPosts = useIsFetching({ queryKey: ['posts'] })
25
+ *
26
+ * return isFetchingPosts ? <span>Refreshing posts...</span> : null
27
+ * }
26
28
  * ```
27
29
  *
28
30
  * @example
@@ -21,14 +21,16 @@ import { useSyncExternalStore } from './utils'
21
21
  * Unlike queries, mutations are typically used to create/update/delete data or perform server side-effects.
22
22
  * `useMutation` is the hook for that.
23
23
  *
24
- * @see {@link mutationOptions} to share these options across multiple `useMutation` call sites.
24
+ * @see {@link mutationOptions} to share these options across multiple `useMutation` call sites, or to look
25
+ * the mutation up elsewhere via its `mutationKey` (e.g. with `useMutationState`).
25
26
  * @param options - The {@link UseMutationOptions} to use — everything you can pass to `useMutation`.
26
27
  * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will
27
28
  * be used.
28
29
  * @returns `mutate`/`mutateAsync` also accept per-call `onSuccess`/`onError`/`onSettled` callbacks as a second
29
30
  * argument, useful for triggering call-site side effects (e.g. navigation) without coupling them to the shared
30
- * mutation definition. If you make multiple requests, `onSuccess` will fire only after the latest call you've
31
- * made.
31
+ * mutation definition. Hook-level callbacks (passed to `options`) fire for every mutation; per-call callbacks
32
+ * fire only for the latest call you've made, and only while the component is still mounted — unmounting before
33
+ * the mutation settles removes the subscription and prevents them from firing.
32
34
  *
33
35
  * @example
34
36
  * ```tsx
@@ -105,11 +107,11 @@ import { useSyncExternalStore } from './utils'
105
107
  * newTodo,
106
108
  * ])
107
109
  *
108
- * // Passed to `onError` as `context` if the mutation fails.
110
+ * // Passed to `onError` as `onMutateResult` if the mutation fails.
109
111
  * return { previousTodos }
110
112
  * },
111
- * onError: (_err, _newTodo, context) => {
112
- * queryClient.setQueryData(['todos'], context?.previousTodos)
113
+ * onError: (_err, _newTodo, onMutateResult) => {
114
+ * queryClient.setQueryData(['todos'], onMutateResult?.previousTodos)
113
115
  * },
114
116
  * onSettled: () => {
115
117
  * queryClient.invalidateQueries({ queryKey: ['todos'] })
@@ -124,7 +126,7 @@ import { useSyncExternalStore } from './utils'
124
126
  *
125
127
  * @example
126
128
  * Callbacks passed per call to `mutate` only fire for the last call — `mutateAsync` gives you a
127
- * promise per call instead, so you can wait for all of them:
129
+ * promise per call instead, so you can wait for all of them when they succeed:
128
130
  * ```tsx
129
131
  * import { useMutation, useQueryClient } from '@tanstack/preact-query'
130
132
  *
@@ -168,13 +170,13 @@ import { useSyncExternalStore } from './utils'
168
170
  * })
169
171
  *
170
172
  * async function handleAddAll(todos: Array<string>) {
171
- * const results = await Promise.allSettled(
173
+ * const addResults = await Promise.allSettled(
172
174
  * todos.map((todo) => addMutation.mutateAsync(todo)),
173
175
  * )
174
176
  *
175
- * results.forEach((result, index) => {
176
- * if (result.status === 'rejected') {
177
- * console.error(`Failed to add "${todos[index]}":`, result.reason)
177
+ * addResults.forEach((addResult, index) => {
178
+ * if (addResult.status === 'rejected') {
179
+ * console.error(`Failed to add "${todos[index]}":`, addResult.reason)
178
180
  * }
179
181
  * })
180
182
  * }