@tanstack/solid-query 5.94.5 → 6.0.0-alpha.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.
package/src/useQueries.ts CHANGED
@@ -1,15 +1,11 @@
1
1
  import { QueriesObserver, noop } from '@tanstack/query-core'
2
- import { createStore, unwrap } from 'solid-js/store'
3
2
  import {
4
- batch,
5
- createComputed,
3
+ createEffect,
6
4
  createMemo,
7
- createRenderEffect,
8
- createResource,
9
- mergeProps,
10
- on,
5
+ createStore,
6
+ merge,
11
7
  onCleanup,
12
- onMount,
8
+ reconcile,
13
9
  } from 'solid-js'
14
10
  import { useQueryClient } from './QueryClientProvider'
15
11
  import { useIsRestoring } from './isRestoring'
@@ -122,7 +118,7 @@ type GetResults<T> =
122
118
  UseQueryResult
123
119
 
124
120
  /**
125
- * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param
121
+ * QueriesOptions reducer recursively snapshots function arguments to infer/enforce type param
126
122
  */
127
123
  type QueriesOptions<
128
124
  T extends Array<any>,
@@ -201,18 +197,15 @@ export function useQueries<
201
197
 
202
198
  const defaultedQueries = createMemo(() =>
203
199
  queriesOptions().queries.map((options) =>
204
- mergeProps(
205
- client().defaultQueryOptions(options as QueryObserverOptions),
206
- {
207
- get _optimisticResults() {
208
- return isRestoring() ? 'isRestoring' : 'optimistic'
209
- },
200
+ merge(client().defaultQueryOptions(options as QueryObserverOptions), {
201
+ get _optimisticResults() {
202
+ return isRestoring() ? 'isRestoring' : 'optimistic'
210
203
  },
211
- ),
204
+ }),
212
205
  ),
213
206
  )
214
207
 
215
- const observer = new QueriesObserver(
208
+ const observer = new QueriesObserver<TCombinedResult>(
216
209
  client(),
217
210
  defaultedQueries(),
218
211
  queriesOptions().combine
@@ -222,122 +215,63 @@ export function useQueries<
222
215
  : undefined,
223
216
  )
224
217
 
225
- const [state, setState] = createStore<TCombinedResult>(
226
- observer.getOptimisticResult(
227
- defaultedQueries(),
228
- (queriesOptions() as QueriesObserverOptions<TCombinedResult>).combine,
229
- )[1](),
218
+ // Get initial optimistic result
219
+ const [, getCombinedResult] = observer.getOptimisticResult(
220
+ defaultedQueries(),
221
+ (queriesOptions() as QueriesObserverOptions<TCombinedResult>).combine,
230
222
  )
231
223
 
232
- createRenderEffect(
233
- on(
234
- () => queriesOptions().queries.length,
235
- () =>
236
- setState(
237
- observer.getOptimisticResult(
238
- defaultedQueries(),
239
- (queriesOptions() as QueriesObserverOptions<TCombinedResult>)
240
- .combine,
241
- )[1](),
242
- ),
243
- ),
244
- )
224
+ const initialResult = getCombinedResult()
245
225
 
246
- const dataResources = createMemo(
247
- on(
248
- () => state.length,
249
- () =>
250
- state.map((queryRes) => {
251
- const dataPromise = () =>
252
- new Promise((resolve) => {
253
- if (queryRes.isFetching && queryRes.isLoading) return
254
- resolve(unwrap(queryRes.data))
255
- })
256
- return createResource(dataPromise)
257
- }),
258
- ),
226
+ // Store the combined result in a reactive store
227
+ const [state, setState] = createStore<Array<QueryObserverResult>>(
228
+ (Array.isArray(initialResult)
229
+ ? initialResult
230
+ : [initialResult]) as Array<QueryObserverResult>,
259
231
  )
260
232
 
261
- batch(() => {
262
- const dataResources_ = dataResources()
263
- for (let index = 0; index < dataResources_.length; index++) {
264
- const dataResource = dataResources_[index]!
265
- dataResource[1].mutate(() => unwrap(state[index]!.data))
266
- dataResource[1].refetch()
267
- }
268
- })
269
-
270
- let taskQueue: Array<() => void> = []
271
- const subscribeToObserver = () =>
272
- observer.subscribe((result) => {
273
- taskQueue.push(() => {
274
- batch(() => {
275
- const dataResources_ = dataResources()
276
- for (let index = 0; index < dataResources_.length; index++) {
277
- const dataResource = dataResources_[index]!
278
- const unwrappedResult = { ...unwrap(result[index]) }
279
- // @ts-expect-error typescript pedantry regarding the possible range of index
280
- setState(index, unwrap(unwrappedResult))
281
- dataResource[1].mutate(() => unwrap(state[index]!.data))
282
- dataResource[1].refetch()
283
- }
284
- })
285
- })
286
-
287
- queueMicrotask(() => {
288
- const taskToRun = taskQueue.pop()
289
- if (taskToRun) taskToRun()
290
- taskQueue = []
291
- })
292
- })
293
-
233
+ // Subscribe to the observer for updates reactively.
234
+ // When isRestoring is true (persist client is restoring), we defer
235
+ // subscription until restoring completes.
294
236
  let unsubscribe: () => void = noop
295
- createComputed<() => void>((cleanup) => {
296
- cleanup?.()
297
- unsubscribe = isRestoring() ? noop : subscribeToObserver()
298
- // cleanup needs to be scheduled after synchronous effects take place
299
- return () => queueMicrotask(unsubscribe)
300
- })
301
- onCleanup(unsubscribe)
237
+ createEffect(
238
+ () => {
239
+ if (!isRestoring()) {
240
+ unsubscribe = observer.subscribe((result) => {
241
+ setState(
242
+ reconcile(
243
+ [...result] as Array<QueryObserverResult>,
244
+ // Use a key function that returns undefined so reconcile
245
+ // uses positional matching and recursively updates nested properties
246
+ () => undefined,
247
+ ),
248
+ )
249
+ })
250
+ }
251
+ },
252
+ () => {},
253
+ )
302
254
 
303
- onMount(() => {
304
- observer.setQueries(
305
- defaultedQueries(),
306
- queriesOptions().combine
307
- ? ({
308
- combine: queriesOptions().combine,
309
- } as QueriesObserverOptions<TCombinedResult>)
310
- : undefined,
311
- )
255
+ onCleanup(() => {
256
+ unsubscribe()
312
257
  })
313
258
 
314
- createComputed(() => {
259
+ // Update observer queries when options change reactively
260
+ const trackedDefaultedQueries = createMemo(() => {
261
+ const queries = defaultedQueries()
315
262
  observer.setQueries(
316
- defaultedQueries(),
263
+ queries,
317
264
  queriesOptions().combine
318
265
  ? ({
319
266
  combine: queriesOptions().combine,
320
267
  } as QueriesObserverOptions<TCombinedResult>)
321
268
  : undefined,
322
269
  )
270
+ return queries
323
271
  })
324
272
 
325
- const handler = (index: number) => ({
326
- get(target: QueryObserverResult, prop: keyof QueryObserverResult): any {
327
- if (prop === 'data') {
328
- return dataResources()[index]![0]()
329
- }
330
- return Reflect.get(target, prop)
331
- },
332
- })
333
-
334
- const getProxies = () =>
335
- state.map((s, index) => {
336
- return new Proxy(s, handler(index))
337
- })
338
-
339
- const [proxyState, setProxyState] = createStore(getProxies())
340
- createRenderEffect(() => setProxyState(getProxies()))
273
+ // Force read of trackedDefaultedQueries to ensure it runs
274
+ void trackedDefaultedQueries
341
275
 
342
- return proxyState as TCombinedResult
276
+ return state as unknown as TCombinedResult
343
277
  }