Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/core/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ export function getResolvedQueryConfig<TResult, TError>(
return resolvedConfig
}

export function isResolvedQueryConfig<TResult, TError>(
config: any
): config is ResolvedQueryConfig<TResult, TError> {
return Boolean(config.queryHash)
}

export function getResolvedMutationConfig<
TResult,
TError,
Expand Down
9 changes: 9 additions & 0 deletions src/core/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,9 @@ export class Query<TResult, TError> {
this.continue()
}

/**
* @deprectated
*/
subscribe(
listener?: UpdateListener<TResult, TError>
): QueryObserver<TResult, TError> {
Expand Down Expand Up @@ -319,6 +322,9 @@ export class Query<TResult, TError> {
}
}

/**
* @deprectated
*/
refetch(
options?: RefetchOptions,
config?: ResolvedQueryConfig<TResult, TError>
Expand All @@ -332,6 +338,9 @@ export class Query<TResult, TError> {
return promise
}

/**
* @deprectated
*/
fetchMore(
fetchMoreVariable?: unknown,
options?: FetchMoreOptions,
Expand Down
31 changes: 31 additions & 0 deletions src/core/queryCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
ResolvedQueryConfig,
} from './types'
import { notifyManager } from './notifyManager'
import { QueryObserver } from './queryObserver'

// TYPES

Expand Down Expand Up @@ -455,6 +456,36 @@ export class QueryCache {
return promise
}

// Parameter syntax
watchQuery<TResult = unknown, TError = unknown>(
queryKey: QueryKey,
queryConfig?: QueryConfig<TResult, TError>
): QueryObserver<TResult, TError>

// Parameter syntax with query function
watchQuery<TResult, TError, TArgs extends TypedQueryFunctionArgs>(
queryKey: QueryKey,
queryFn: TypedQueryFunction<TResult, TArgs>,
queryConfig?: QueryConfig<TResult, TError>
): QueryObserver<TResult, TError>

watchQuery<TResult = unknown, TError = unknown>(
queryKey: QueryKey,
queryFn: QueryFunction<TResult>,
queryConfig?: QueryConfig<TResult, TError>
): QueryObserver<TResult, TError>

// Implementation
watchQuery<TResult, TError>(
arg1: any,
arg2?: any,
arg3?: any
): QueryObserver<TResult, TError> {
const [queryKey, config] = getQueryArgs<TResult, TError>(arg1, arg2, arg3)
const resolvedConfig = this.getResolvedQueryConfig(queryKey, config)
return new QueryObserver(resolvedConfig)
}

setQueryData<TResult, TError = unknown>(
queryKey: QueryKey,
updater: Updater<TResult | undefined, TResult>,
Expand Down
114 changes: 65 additions & 49 deletions src/core/queryObserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import {
noop,
} from './utils'
import { notifyManager } from './notifyManager'
import type { QueryResult, ResolvedQueryConfig } from './types'
import type { QueryConfig, QueryResult, ResolvedQueryConfig } from './types'
import type { Query, Action, FetchMoreOptions, RefetchOptions } from './query'
import { DEFAULT_CONFIG, isResolvedQueryConfig } from './config'

export type UpdateListener<TResult, TError> = (
result: QueryResult<TResult, TError>
Expand Down Expand Up @@ -41,13 +42,14 @@ export class QueryObserver<TResult, TError> {
this.remove = this.remove.bind(this)
this.refetch = this.refetch.bind(this)
this.fetchMore = this.fetchMore.bind(this)
this.unsubscribe = this.unsubscribe.bind(this)

// Subscribe to the query
this.updateQuery()
}

subscribe(listener?: UpdateListener<TResult, TError>): () => void {
this.listener = listener
this.listener = listener || noop
this.currentQuery.subscribeObserver(this)

if (
Expand All @@ -60,7 +62,8 @@ export class QueryObserver<TResult, TError> {
}

this.updateTimers()
return this.unsubscribe.bind(this)

return this.unsubscribe
}

unsubscribe(): void {
Expand All @@ -69,11 +72,19 @@ export class QueryObserver<TResult, TError> {
this.currentQuery.unsubscribeObserver(this)
}

updateConfig(config: ResolvedQueryConfig<TResult, TError>): void {
updateConfig(
config: QueryConfig<TResult, TError> | ResolvedQueryConfig<TResult, TError>
): void {
const prevConfig = this.config
const prevQuery = this.currentQuery

this.config = config
this.config = isResolvedQueryConfig(config)
? config
: this.config.queryCache.getResolvedQueryConfig(
this.config.queryKey,
config
)

this.updateQuery()

// Take no further actions if there is no subscriber
Expand Down Expand Up @@ -143,6 +154,11 @@ export class QueryObserver<TResult, TError> {
}

fetch(): Promise<TResult | undefined> {
// Never try to fetch if no query function has been set
if (this.config.queryFn === DEFAULT_CONFIG.queries?.queryFn) {
return Promise.resolve(this.currentResult.data)
}

return this.currentQuery.fetch(undefined, this.config).catch(noop)
}

Expand All @@ -157,50 +173,6 @@ export class QueryObserver<TResult, TError> {
}
}

private notify(options: NotifyOptions): void {
const { config, currentResult, currentQuery, listener } = this
const { onSuccess, onSettled, onError } = config

notifyManager.batch(() => {
// First trigger the configuration callbacks
if (options.onSuccess) {
if (onSuccess) {
notifyManager.schedule(() => {
onSuccess(currentResult.data!)
})
}
if (onSettled) {
notifyManager.schedule(() => {
onSettled(currentResult.data!, null)
})
}
} else if (options.onError) {
if (onError) {
notifyManager.schedule(() => {
onError(currentResult.error!)
})
}
if (onSettled) {
notifyManager.schedule(() => {
onSettled(undefined, currentResult.error!)
})
}
}

// Then trigger the listener
if (options.listener && listener) {
notifyManager.schedule(() => {
listener(currentResult)
})
}

// Then the global listeners
if (options.globalListeners) {
config.queryCache.notifyGlobalListeners(currentQuery)
}
})
}

private updateStaleTimeout(): void {
if (isServer) {
return
Expand Down Expand Up @@ -393,4 +365,48 @@ export class QueryObserver<TResult, TError> {

this.notify(notifyOptions)
}

private notify(options: NotifyOptions): void {
const { config, currentResult, currentQuery, listener } = this
const { onSuccess, onSettled, onError } = config

notifyManager.batch(() => {
// First trigger the configuration callbacks
if (options.onSuccess) {
if (onSuccess) {
notifyManager.schedule(() => {
onSuccess(currentResult.data!)
})
}
if (onSettled) {
notifyManager.schedule(() => {
onSettled(currentResult.data!, null)
})
}
} else if (options.onError) {
if (onError) {
notifyManager.schedule(() => {
onError(currentResult.error!)
})
}
if (onSettled) {
notifyManager.schedule(() => {
onSettled(undefined, currentResult.error!)
})
}
}

// Then trigger the listener
if (options.listener && listener) {
notifyManager.schedule(() => {
listener(currentResult)
})
}

// Then the global listeners
if (options.globalListeners) {
config.queryCache.notifyGlobalListeners(currentQuery)
}
})
}
}
Loading