@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/src/useQuery.ts CHANGED
@@ -14,6 +14,167 @@ import type {
14
14
  UndefinedInitialDataOptions,
15
15
  } from './queryOptions'
16
16
 
17
+ /**
18
+ * @see {@link queryOptions} to share these options between `useQuery` and imperative APIs like `queryClient.query`.
19
+ * @param options - An accessor returning the {@link UndefinedInitialDataOptions} to use — everything you can
20
+ * pass to `useQuery`.
21
+ * @param queryClient - An accessor for a custom `QueryClient`. Otherwise, the one from the nearest context
22
+ * will be used.
23
+ * @returns The current query result, as a Solid store. `status` is `pending` if there is no cached data to
24
+ * display, `error` if the last fetch attempt failed, or `success` if the query has data to display.
25
+ * `isPending`/`isSuccess`/`isError` are derived booleans for convenience.
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * import { For, Match, Switch } from 'solid-js'
30
+ * import { useQuery } from '@tanstack/solid-query'
31
+ *
32
+ * function Posts() {
33
+ * const postsQuery = useQuery(() => ({
34
+ * queryKey: ['posts'],
35
+ * queryFn: fetchPosts,
36
+ * }))
37
+ *
38
+ * return (
39
+ * <Switch>
40
+ * <Match when={postsQuery.isPending}>Loading...</Match>
41
+ * <Match when={postsQuery.isError}>Error: {postsQuery.error.message}</Match>
42
+ * <Match when={postsQuery.isSuccess}>
43
+ * <ul>
44
+ * <For each={postsQuery.data}>{(post) => <li>{post.title}</li>}</For>
45
+ * </ul>
46
+ * <div>{postsQuery.isFetching ? 'Background Updating...' : ' '}</div>
47
+ * </Match>
48
+ * </Switch>
49
+ * )
50
+ * }
51
+ * ```
52
+ *
53
+ * @example
54
+ * `select` derives whatever `data` a component needs from the cached value, without changing what's
55
+ * actually stored in the cache — the cache still holds the full `Post[]`, but `data` here is a `number`:
56
+ * ```tsx
57
+ * import { Match, Switch } from 'solid-js'
58
+ * import { useQuery } from '@tanstack/solid-query'
59
+ *
60
+ * function PostCount() {
61
+ * const postsQuery = useQuery(() => ({
62
+ * queryKey: ['posts'],
63
+ * queryFn: fetchPosts,
64
+ * select: (posts) => posts.length,
65
+ * }))
66
+ *
67
+ * return (
68
+ * <Switch>
69
+ * <Match when={postsQuery.isPending}>Loading...</Match>
70
+ * <Match when={postsQuery.isError}>Error: {postsQuery.error.message}</Match>
71
+ * <Match when={postsQuery.isSuccess}>{postsQuery.data} posts</Match>
72
+ * </Switch>
73
+ * )
74
+ * }
75
+ * ```
76
+ *
77
+ * @example
78
+ * A dependent query, only enabled once `postId` is set:
79
+ * ```tsx
80
+ * import { Match, Switch } from 'solid-js'
81
+ * import { useQuery } from '@tanstack/solid-query'
82
+ *
83
+ * function Post(props: { postId: number | undefined }) {
84
+ * const postQuery = useQuery(() => ({
85
+ * queryKey: ['post', props.postId],
86
+ * queryFn: () => fetchPost(props.postId!),
87
+ * enabled: props.postId != null,
88
+ * }))
89
+ *
90
+ * return (
91
+ * <Switch fallback={<h1>{postQuery.data?.title}</h1>}>
92
+ * <Match when={props.postId == null}>Select a post</Match>
93
+ * <Match when={postQuery.isLoading}>Loading...</Match>
94
+ * <Match when={postQuery.isError}>Error: {postQuery.error.message}</Match>
95
+ * </Switch>
96
+ * )
97
+ * }
98
+ * ```
99
+ *
100
+ * @example
101
+ * The same dependent query, using `skipToken` to disable it in a type-safe way instead of relying on
102
+ * `enabled`. The non-null assertion is still needed — Solid's `props` narrowing doesn't survive into the
103
+ * `queryFn` closure the way a local `const` would — but `skipToken` keeps `queryFn`'s return type accurate
104
+ * without it. `refetch` doesn't work while `queryFn` is `skipToken` — use `enabled: false` instead if you
105
+ * need to trigger the query manually:
106
+ * ```tsx
107
+ * import { Match, Switch } from 'solid-js'
108
+ * import { skipToken, useQuery } from '@tanstack/solid-query'
109
+ *
110
+ * function Post(props: { postId: number | undefined }) {
111
+ * const postQuery = useQuery(() => ({
112
+ * queryKey: ['post', props.postId],
113
+ * queryFn: props.postId != null ? () => fetchPost(props.postId!) : skipToken,
114
+ * }))
115
+ *
116
+ * return (
117
+ * <Switch fallback={<h1>{postQuery.data?.title}</h1>}>
118
+ * <Match when={props.postId == null}>Select a post</Match>
119
+ * <Match when={postQuery.isLoading}>Loading...</Match>
120
+ * <Match when={postQuery.isError}>Error: {postQuery.error.message}</Match>
121
+ * </Switch>
122
+ * )
123
+ * }
124
+ * ```
125
+ *
126
+ * @example
127
+ * Seeding a detail query from an already-cached list, to skip the loading state:
128
+ * ```tsx
129
+ * import { useQuery, useQueryClient } from '@tanstack/solid-query'
130
+ *
131
+ * function Post(props: { postId: number }) {
132
+ * const queryClient = useQueryClient()
133
+ *
134
+ * const postQuery = useQuery(() => ({
135
+ * queryKey: ['post', props.postId],
136
+ * queryFn: () => fetchPost(props.postId),
137
+ * initialData: () =>
138
+ * queryClient
139
+ * .getQueryData<Array<Post>>(['posts'])
140
+ * ?.find((post) => post.id === props.postId),
141
+ * }))
142
+ *
143
+ * return postQuery.isError ? <span>Error: {postQuery.error.message}</span> : <h1>{postQuery.data?.title}</h1>
144
+ * }
145
+ * ```
146
+ *
147
+ * @example
148
+ * Paginated data, keeping the previous page's data visible while the next page loads:
149
+ * ```tsx
150
+ * import { For, createSignal } from 'solid-js'
151
+ * import { keepPreviousData, useQuery } from '@tanstack/solid-query'
152
+ *
153
+ * function Posts() {
154
+ * const [page, setPage] = createSignal(0)
155
+ *
156
+ * const postsQuery = useQuery(() => ({
157
+ * queryKey: ['posts', page()],
158
+ * queryFn: () => fetchPosts(page()),
159
+ * placeholderData: keepPreviousData,
160
+ * }))
161
+ *
162
+ * return (
163
+ * <div>
164
+ * <ul>
165
+ * <For each={postsQuery.data}>{(post) => <li>{post.title}</li>}</For>
166
+ * </ul>
167
+ * <button
168
+ * disabled={postsQuery.isPlaceholderData}
169
+ * onClick={() => setPage((old) => old + 1)}
170
+ * >
171
+ * Next Page
172
+ * </button>
173
+ * </div>
174
+ * )
175
+ * }
176
+ * ```
177
+ */
17
178
  export function useQuery<
18
179
  TQueryFnData = unknown,
19
180
  TError = DefaultError,
@@ -24,6 +185,44 @@ export function useQuery<
24
185
  queryClient?: () => QueryClient,
25
186
  ): UseQueryResult<TData, TError>
26
187
 
188
+ /**
189
+ * This overload is selected when `initialData` is set, so the resulting `data` is never `undefined`.
190
+ *
191
+ * @see {@link queryOptions} to share these options between `useQuery` and imperative APIs like `queryClient.query`.
192
+ * @param options - An accessor returning the {@link DefinedInitialDataOptions} to use — everything you can
193
+ * pass to `useQuery`, with `initialData` set.
194
+ * @param queryClient - An accessor for a custom `QueryClient`. Otherwise, the one from the nearest context
195
+ * will be used.
196
+ * @returns The current query result, as a Solid store, typed so that `status` is `success` — or `error` if a
197
+ * fetch attempt fails while keeping the existing data (`status` never resolves to `pending` in this overload's
198
+ * type, since `initialData` guarantees data upfront). `isSuccess`/`isError` are derived booleans for
199
+ * convenience.
200
+ *
201
+ * @example
202
+ * ```tsx
203
+ * import { For } from 'solid-js'
204
+ * import { useQuery } from '@tanstack/solid-query'
205
+ *
206
+ * function Posts() {
207
+ * // `postsQuery.data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the
208
+ * // list stays visible alongside the error.
209
+ * const postsQuery = useQuery(() => ({
210
+ * queryKey: ['posts'],
211
+ * queryFn: fetchPosts,
212
+ * initialData: [],
213
+ * }))
214
+ *
215
+ * return (
216
+ * <div>
217
+ * {postsQuery.isError ? <span>Error: {postsQuery.error.message}</span> : null}
218
+ * <ul>
219
+ * <For each={postsQuery.data}>{(post) => <li>{post.title}</li>}</For>
220
+ * </ul>
221
+ * </div>
222
+ * )
223
+ * }
224
+ * ```
225
+ */
27
226
  export function useQuery<
28
227
  TQueryFnData = unknown,
29
228
  TError = DefaultError,