snapshot of https://github.com/TanStack/query.git (main, 2026-09-16; blobs > 131072B omitted)
This commit is contained in:
107
packages/svelte-query/src/createBaseQuery.svelte.ts
Normal file
107
packages/svelte-query/src/createBaseQuery.svelte.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import { useIsRestoring } from './useIsRestoring.js'
|
||||
import { useQueryClient } from './useQueryClient.js'
|
||||
import { createRawRef } from './containers.svelte.js'
|
||||
import { watchChanges } from './utils.svelte.js'
|
||||
import type { QueryClient, QueryKey, QueryObserver } from '@tanstack/query-core'
|
||||
import type {
|
||||
Accessor,
|
||||
CreateBaseQueryOptions,
|
||||
CreateBaseQueryResult,
|
||||
} from './types.js'
|
||||
|
||||
/**
|
||||
* Base implementation for `createQuery` and `createInfiniteQuery`
|
||||
* @param options - A function that returns query options
|
||||
* @param Observer - The observer from query-core
|
||||
* @param queryClient - Custom query client which overrides provider
|
||||
*/
|
||||
export function createBaseQuery<
|
||||
TQueryFnData,
|
||||
TError,
|
||||
TData,
|
||||
TQueryData,
|
||||
TQueryKey extends QueryKey,
|
||||
>(
|
||||
options: Accessor<
|
||||
CreateBaseQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>
|
||||
>,
|
||||
Observer: typeof QueryObserver,
|
||||
queryClient?: Accessor<QueryClient>,
|
||||
): CreateBaseQueryResult<TData, TError> {
|
||||
/** Load query client */
|
||||
const client = $derived(useQueryClient(queryClient?.()))
|
||||
const isRestoring = useIsRestoring()
|
||||
|
||||
const resolvedOptions = $derived.by(() => {
|
||||
const opts = client.defaultQueryOptions(options())
|
||||
opts._optimisticResults = isRestoring.current ? 'isRestoring' : 'optimistic'
|
||||
return opts
|
||||
})
|
||||
|
||||
/** Creates the observer */
|
||||
// svelte-ignore state_referenced_locally - intentional, initial value
|
||||
let observer = $state(
|
||||
new Observer<TQueryFnData, TError, TData, TQueryData, TQueryKey>(
|
||||
client,
|
||||
resolvedOptions,
|
||||
),
|
||||
)
|
||||
watchChanges(
|
||||
() => client,
|
||||
'pre',
|
||||
() => {
|
||||
observer = new Observer<
|
||||
TQueryFnData,
|
||||
TError,
|
||||
TData,
|
||||
TQueryData,
|
||||
TQueryKey
|
||||
>(client, resolvedOptions)
|
||||
},
|
||||
)
|
||||
|
||||
function createResult() {
|
||||
const result = observer.getOptimisticResult(resolvedOptions)
|
||||
return !resolvedOptions.notifyOnChangeProps
|
||||
? observer.trackResult(result)
|
||||
: result
|
||||
}
|
||||
const [query, update] = createRawRef(
|
||||
// svelte-ignore state_referenced_locally - intentional, initial value
|
||||
createResult(),
|
||||
)
|
||||
|
||||
$effect(() => {
|
||||
const unsubscribe = isRestoring.current
|
||||
? () => undefined
|
||||
: observer.subscribe(() => update(createResult()))
|
||||
observer.updateResult()
|
||||
return unsubscribe
|
||||
})
|
||||
|
||||
watchChanges(
|
||||
() => resolvedOptions,
|
||||
'pre',
|
||||
() => {
|
||||
observer.setOptions(resolvedOptions)
|
||||
},
|
||||
)
|
||||
watchChanges(
|
||||
() => [resolvedOptions, observer],
|
||||
'pre',
|
||||
() => {
|
||||
// The only reason this is necessary is because of `isRestoring`.
|
||||
// Because we don't subscribe while restoring, the following can occur:
|
||||
// - `isRestoring` is true
|
||||
// - `isRestoring` becomes false
|
||||
// - `observer.subscribe` and `observer.updateResult` is called in the above effect,
|
||||
// but the subsequent `fetch` has already completed
|
||||
// - `result` misses the intermediate restored-but-not-fetched state
|
||||
//
|
||||
// this could technically be its own effect but that doesn't seem necessary
|
||||
update(createResult())
|
||||
},
|
||||
)
|
||||
|
||||
return query
|
||||
}
|
||||
Reference in New Issue
Block a user