Skip to content

Commit 00b9e96

Browse files
authored
refactor: optimize render path and improve type safety (#984)
1 parent 7730fee commit 00b9e96

15 files changed

+220
-243
lines changed

src/core/config.ts

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { stableStringify } from './utils'
2-
import {
2+
import type {
33
ArrayQueryKey,
4+
MutationConfig,
5+
QueryConfig,
46
QueryKey,
57
QueryKeySerializerFunction,
68
ReactQueryConfig,
7-
QueryConfig,
8-
MutationConfig,
9+
ResolvedQueryConfig,
910
} from './types'
11+
import type { QueryCache } from './queryCache'
1012

1113
// TYPES
1214

@@ -47,20 +49,19 @@ export const defaultQueryKeySerializerFn: QueryKeySerializerFunction = (
4749
* 2. Defaults from the query cache.
4850
* 3. Query/mutation config provided to the query cache method.
4951
*/
50-
export const DEFAULT_STALE_TIME = 0
51-
export const DEFAULT_CACHE_TIME = 5 * 60 * 1000
5252
export const DEFAULT_CONFIG: ReactQueryConfig = {
5353
queries: {
54-
cacheTime: DEFAULT_CACHE_TIME,
54+
cacheTime: 5 * 60 * 1000,
5555
enabled: true,
5656
notifyOnStatusChange: true,
57+
queryFn: () => Promise.reject(),
5758
queryKeySerializerFn: defaultQueryKeySerializerFn,
5859
refetchOnMount: true,
5960
refetchOnReconnect: true,
6061
refetchOnWindowFocus: true,
6162
retry: 3,
6263
retryDelay: attemptIndex => Math.min(1000 * 2 ** attemptIndex, 30000),
63-
staleTime: DEFAULT_STALE_TIME,
64+
staleTime: 0,
6465
structuralSharing: true,
6566
},
6667
}
@@ -85,35 +86,44 @@ export function mergeReactQueryConfigs(
8586
}
8687
}
8788

88-
export function getDefaultedQueryConfig<TResult, TError>(
89-
queryCacheConfig?: ReactQueryConfig,
89+
export function getResolvedQueryConfig<TResult, TError>(
90+
queryCache: QueryCache,
91+
queryKey: QueryKey,
9092
contextConfig?: ReactQueryConfig,
91-
config?: QueryConfig<TResult, TError>,
92-
configOverrides?: QueryConfig<TResult, TError>
93-
): QueryConfig<TResult, TError> {
94-
return {
93+
config?: QueryConfig<TResult, TError>
94+
): ResolvedQueryConfig<TResult, TError> {
95+
const queryCacheConfig = queryCache.getDefaultConfig()
96+
97+
const resolvedConfig = {
9598
...DEFAULT_CONFIG.shared,
9699
...DEFAULT_CONFIG.queries,
97100
...queryCacheConfig?.shared,
98101
...queryCacheConfig?.queries,
99102
...contextConfig?.shared,
100103
...contextConfig?.queries,
101104
...config,
102-
...configOverrides,
103-
} as QueryConfig<TResult, TError>
105+
} as ResolvedQueryConfig<TResult, TError>
106+
107+
const result = resolvedConfig.queryKeySerializerFn(queryKey)
108+
109+
resolvedConfig.queryCache = queryCache
110+
resolvedConfig.queryHash = result[0]
111+
resolvedConfig.queryKey = result[1]
112+
113+
return resolvedConfig
104114
}
105115

106-
export function getDefaultedMutationConfig<
116+
export function getResolvedMutationConfig<
107117
TResult,
108118
TError,
109119
TVariables,
110120
TSnapshot
111121
>(
112-
queryCacheConfig?: ReactQueryConfig,
122+
queryCache: QueryCache,
113123
contextConfig?: ReactQueryConfig,
114-
config?: MutationConfig<TResult, TError, TVariables, TSnapshot>,
115-
configOverrides?: MutationConfig<TResult, TError, TVariables, TSnapshot>
124+
config?: MutationConfig<TResult, TError, TVariables, TSnapshot>
116125
): MutationConfig<TResult, TError, TVariables, TSnapshot> {
126+
const queryCacheConfig = queryCache.getDefaultConfig()
117127
return {
118128
...DEFAULT_CONFIG.shared,
119129
...DEFAULT_CONFIG.mutations,
@@ -122,6 +132,5 @@ export function getDefaultedMutationConfig<
122132
...contextConfig?.shared,
123133
...contextConfig?.mutations,
124134
...config,
125-
...configOverrides,
126135
} as MutationConfig<TResult, TError, TVariables, TSnapshot>
127136
}

src/core/query.ts

Lines changed: 21 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,16 @@ import {
1010
isOnline,
1111
isServer,
1212
isValidTimeout,
13-
noop,
1413
replaceEqualDeep,
1514
sleep,
1615
} from './utils'
1716
import {
1817
ArrayQueryKey,
1918
InitialDataFunction,
2019
IsFetchingMoreValue,
21-
QueryConfig,
2220
QueryFunction,
2321
QueryStatus,
22+
ResolvedQueryConfig,
2423
} from './types'
2524
import type { QueryCache } from './queryCache'
2625
import { QueryObserver, UpdateListener } from './queryObserver'
@@ -101,7 +100,7 @@ export type Action<TResult, TError> =
101100
export class Query<TResult, TError> {
102101
queryKey: ArrayQueryKey
103102
queryHash: string
104-
config: QueryConfig<TResult, TError>
103+
config: ResolvedQueryConfig<TResult, TError>
105104
observers: QueryObserver<TResult, TError>[]
106105
state: QueryState<TResult, TError>
107106
cacheTime: number
@@ -113,24 +112,20 @@ export class Query<TResult, TError> {
113112
private continueFetch?: () => void
114113
private isTransportCancelable?: boolean
115114

116-
constructor(
117-
queryKey: ArrayQueryKey,
118-
queryHash: string,
119-
config: QueryConfig<TResult, TError>
120-
) {
115+
constructor(config: ResolvedQueryConfig<TResult, TError>) {
121116
this.config = config
122-
this.queryKey = queryKey
123-
this.queryHash = queryHash
124-
this.queryCache = config.queryCache!
117+
this.queryKey = config.queryKey
118+
this.queryHash = config.queryHash
119+
this.queryCache = config.queryCache
120+
this.cacheTime = config.cacheTime
125121
this.observers = []
126122
this.state = getDefaultState(config)
127-
this.cacheTime = config.cacheTime!
128123
this.scheduleGc()
129124
}
130125

131-
private updateConfig(config: QueryConfig<TResult, TError>): void {
126+
private updateConfig(config: ResolvedQueryConfig<TResult, TError>): void {
132127
this.config = config
133-
this.cacheTime = Math.max(this.cacheTime, config.cacheTime || 0)
128+
this.cacheTime = Math.max(this.cacheTime, config.cacheTime)
134129
}
135130

136131
private dispatch(action: Action<TResult, TError>): void {
@@ -247,7 +242,7 @@ export class Query<TResult, TError> {
247242
)
248243

249244
if (staleObserver) {
250-
staleObserver.fetch().catch(noop)
245+
staleObserver.fetch()
251246
}
252247

253248
// Continue any paused fetch
@@ -257,14 +252,8 @@ export class Query<TResult, TError> {
257252
subscribe(
258253
listener?: UpdateListener<TResult, TError>
259254
): QueryObserver<TResult, TError> {
260-
const observer = new QueryObserver<TResult, TError>({
261-
queryCache: this.queryCache,
262-
queryKey: this.queryKey,
263-
...this.config,
264-
})
265-
255+
const observer = new QueryObserver(this.config)
266256
observer.subscribe(listener)
267-
268257
return observer
269258
}
270259

@@ -291,7 +280,7 @@ export class Query<TResult, TError> {
291280

292281
async refetch(
293282
options?: RefetchOptions,
294-
config?: QueryConfig<TResult, TError>
283+
config?: ResolvedQueryConfig<TResult, TError>
295284
): Promise<TResult | undefined> {
296285
try {
297286
return await this.fetch(undefined, config)
@@ -305,7 +294,7 @@ export class Query<TResult, TError> {
305294
async fetchMore(
306295
fetchMoreVariable?: unknown,
307296
options?: FetchMoreOptions,
308-
config?: QueryConfig<TResult, TError>
297+
config?: ResolvedQueryConfig<TResult, TError>
309298
): Promise<TResult | undefined> {
310299
return this.fetch(
311300
{
@@ -320,7 +309,7 @@ export class Query<TResult, TError> {
320309

321310
async fetch(
322311
options?: FetchOptions,
323-
config?: QueryConfig<TResult, TError>
312+
config?: ResolvedQueryConfig<TResult, TError>
324313
): Promise<TResult | undefined> {
325314
// If we are already fetching, return current promise
326315
if (this.promise) {
@@ -334,11 +323,6 @@ export class Query<TResult, TError> {
334323

335324
config = this.config
336325

337-
// Check if there is a query function
338-
if (typeof config.queryFn !== 'function') {
339-
return
340-
}
341-
342326
// Get the query function params
343327
const filter = config.queryFnParamsFilter
344328
const params = filter ? filter(this.queryKey) : this.queryKey
@@ -385,12 +369,12 @@ export class Query<TResult, TError> {
385369
}
386370

387371
private async startFetch(
388-
config: QueryConfig<TResult, TError>,
372+
config: ResolvedQueryConfig<TResult, TError>,
389373
params: unknown[],
390374
_options?: FetchOptions
391375
): Promise<TResult> {
392376
// Create function to fetch the data
393-
const fetchData = () => config.queryFn!(...params)
377+
const fetchData = () => config.queryFn(...params)
394378

395379
// Set to fetching state if not already in it
396380
if (!this.state.isFetching) {
@@ -402,7 +386,7 @@ export class Query<TResult, TError> {
402386
}
403387

404388
private async startInfiniteFetch(
405-
config: QueryConfig<TResult, TError>,
389+
config: ResolvedQueryConfig<TResult, TError>,
406390
params: unknown[],
407391
options?: FetchOptions
408392
): Promise<TResult[]> {
@@ -427,7 +411,7 @@ export class Query<TResult, TError> {
427411
cursor = config.getFetchMore(lastPage, pages)
428412
}
429413

430-
const page = await config.queryFn!(...params, cursor)
414+
const page = await config.queryFn(...params, cursor)
431415

432416
return prepend ? [page, ...pages] : [...pages, page]
433417
}
@@ -457,7 +441,7 @@ export class Query<TResult, TError> {
457441
}
458442

459443
private async tryFetchData<T>(
460-
config: QueryConfig<TResult, TError>,
444+
config: ResolvedQueryConfig<TResult, TError>,
461445
fn: QueryFunction<T>
462446
): Promise<T> {
463447
return new Promise<T>((outerResolve, outerReject) => {
@@ -567,7 +551,7 @@ function getLastPage<TResult>(pages: TResult[], previous?: boolean): TResult {
567551
}
568552

569553
function hasMorePages<TResult, TError>(
570-
config: QueryConfig<TResult, TError>,
554+
config: ResolvedQueryConfig<TResult, TError>,
571555
pages: unknown,
572556
previous?: boolean
573557
): boolean | undefined {
@@ -577,7 +561,7 @@ function hasMorePages<TResult, TError>(
577561
}
578562

579563
function getDefaultState<TResult, TError>(
580-
config: QueryConfig<TResult, TError>
564+
config: ResolvedQueryConfig<TResult, TError>
581565
): QueryState<TResult, TError> {
582566
const initialData =
583567
typeof config.initialData === 'function'

0 commit comments

Comments
 (0)