@tanstack/solid-query 6.0.0-beta.6 → 6.0.0-beta.8
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/_tsup-dts-rollup.d.cts +85 -0
- package/build/_tsup-dts-rollup.d.ts +85 -0
- package/build/dev.cjs +196 -18
- package/build/dev.js +198 -20
- package/build/index.cjs +196 -18
- package/build/index.js +198 -20
- package/package.json +6 -6
- package/src/QueryClientProvider.tsx +60 -2
- package/src/hydrationChannel.ts +260 -0
- package/src/useBaseQuery.ts +63 -13
package/src/useBaseQuery.ts
CHANGED
|
@@ -13,8 +13,10 @@ import {
|
|
|
13
13
|
runWithOwner,
|
|
14
14
|
snapshot,
|
|
15
15
|
untrack,
|
|
16
|
+
useContext,
|
|
16
17
|
} from 'solid-js'
|
|
17
18
|
import { useQueryClient } from './QueryClientProvider'
|
|
19
|
+
import { HydrationCoordinatorContext } from './hydrationChannel'
|
|
18
20
|
import { useIsRestoring } from './isRestoring'
|
|
19
21
|
import type { UseBaseQueryOptions } from './types'
|
|
20
22
|
import type { Accessor } from 'solid-js'
|
|
@@ -97,8 +99,14 @@ function reconcileFn<TData, TError>(
|
|
|
97
99
|
}
|
|
98
100
|
|
|
99
101
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
+
* Prepare an observer result for SSR serialization: the resolved resource
|
|
103
|
+
* value is serialized by seroval, which cannot handle functions, so strip
|
|
104
|
+
* `refetch` (and the infinite-query pagers). They come back when the
|
|
105
|
+
* observer attaches on the client.
|
|
106
|
+
*
|
|
107
|
+
* The query's dehydrated cache state does not ride the observer result —
|
|
108
|
+
* it travels through the provider-owned dehydration channel (see
|
|
109
|
+
* `hydrationChannel.ts`).
|
|
102
110
|
*/
|
|
103
111
|
const hydratableObserverResult = <
|
|
104
112
|
TQueryFnData,
|
|
@@ -107,7 +115,7 @@ const hydratableObserverResult = <
|
|
|
107
115
|
TQueryKey extends QueryKey,
|
|
108
116
|
TDataHydratable,
|
|
109
117
|
>(
|
|
110
|
-
|
|
118
|
+
_query: Query<TQueryFnData, TError, TData, TQueryKey>,
|
|
111
119
|
result: QueryObserverResult<TDataHydratable, TError>,
|
|
112
120
|
) => {
|
|
113
121
|
if (!isServer) return result
|
|
@@ -124,15 +132,6 @@ const hydratableObserverResult = <
|
|
|
124
132
|
obj.fetchPreviousPage = undefined
|
|
125
133
|
}
|
|
126
134
|
|
|
127
|
-
// We will also attach the dehydrated state of the query to the result
|
|
128
|
-
// This will be removed on client after hydration
|
|
129
|
-
obj.hydrationData = {
|
|
130
|
-
state: query.state,
|
|
131
|
-
queryKey: query.queryKey,
|
|
132
|
-
queryHash: query.queryHash,
|
|
133
|
-
...(query.meta && { meta: query.meta }),
|
|
134
|
-
}
|
|
135
|
-
|
|
136
135
|
return obj
|
|
137
136
|
}
|
|
138
137
|
|
|
@@ -281,6 +280,46 @@ export function useBaseQuery<
|
|
|
281
280
|
let unsubscribe: (() => void) | null = null
|
|
282
281
|
let disposed = false
|
|
283
282
|
|
|
283
|
+
/**
|
|
284
|
+
* Attach the client subscriber for a component that hydrated from SSR
|
|
285
|
+
* output.
|
|
286
|
+
*
|
|
287
|
+
* During hydration Solid replays the `queryResource` memo below from the
|
|
288
|
+
* serialized SSR value with `Promise` mocked, so the promise executor
|
|
289
|
+
* that normally creates the client subscriber never runs (nor could it:
|
|
290
|
+
* a mount refetch started from inside the replay would never settle).
|
|
291
|
+
* The replay is detected without touching any internals: a real
|
|
292
|
+
* `Promise` runs its executor synchronously, the hydration mock does
|
|
293
|
+
* not, so `executorRan` stays false exactly when this compute was
|
|
294
|
+
* replayed.
|
|
295
|
+
*
|
|
296
|
+
* The subscription is coordinated with the provider's dehydration
|
|
297
|
+
* channel: it attaches once this query's entry has been primed into the
|
|
298
|
+
* cache (or once the channel completes without one), so mount semantics
|
|
299
|
+
* see the hydrated cache state — a still-fresh query does not refetch, a
|
|
300
|
+
* stale one does, and cache writes that landed earlier are reconciled at
|
|
301
|
+
* attach. The wait is per-query, not global-hydration-end: a component
|
|
302
|
+
* hydrated from an early flush goes live while later boundaries are
|
|
303
|
+
* still streaming, so it is not deaf to cache writes, is seen by
|
|
304
|
+
* invalidateQueries' active-query refetch, and cannot be gc'ed while
|
|
305
|
+
* visible. Without a provider (manual `queryClient` option) it falls
|
|
306
|
+
* back to a plain microtask.
|
|
307
|
+
*/
|
|
308
|
+
const coordinator = useContext(HydrationCoordinatorContext)
|
|
309
|
+
const attachHydratedSubscriber = () => {
|
|
310
|
+
if (!unsubscribe && !disposed && !isRestoring()) {
|
|
311
|
+
unsubscribe = createClientSubscriber()
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
const scheduleHydratedAttach = () => {
|
|
315
|
+
const queryHash = untrack(() => observer.getCurrentQuery().queryHash)
|
|
316
|
+
if (coordinator) {
|
|
317
|
+
coordinator.whenQueryPrimed(queryHash, attachHydratedSubscriber)
|
|
318
|
+
} else {
|
|
319
|
+
queueMicrotask(attachHydratedSubscriber)
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
284
323
|
/*
|
|
285
324
|
Fixes #7275
|
|
286
325
|
In a few cases, the observer could unmount before the resource is loaded.
|
|
@@ -325,7 +364,9 @@ export function useBaseQuery<
|
|
|
325
364
|
}
|
|
326
365
|
}
|
|
327
366
|
|
|
328
|
-
|
|
367
|
+
const replayProbe = { executorRan: false }
|
|
368
|
+
const resource = new Promise<ResourceData>((resolve, reject) => {
|
|
369
|
+
replayProbe.executorRan = true
|
|
329
370
|
resolver = resolve
|
|
330
371
|
if (isServer) {
|
|
331
372
|
unsubscribe = createServerSubscriber((data) => {
|
|
@@ -376,6 +417,15 @@ export function useBaseQuery<
|
|
|
376
417
|
)
|
|
377
418
|
}
|
|
378
419
|
})
|
|
420
|
+
|
|
421
|
+
if (!isServer && !replayProbe.executorRan) {
|
|
422
|
+
// Hydration replay: `Promise` was mocked and the executor above never
|
|
423
|
+
// ran, so no subscriber was created. Schedule the attach through the
|
|
424
|
+
// provider's hydration coordinator (see scheduleHydratedAttach).
|
|
425
|
+
scheduleHydratedAttach()
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
return resource
|
|
379
429
|
})
|
|
380
430
|
|
|
381
431
|
onCleanup(() => {
|