Skip to content

Commit 355e866

Browse files
committed
feat: determine staleness locally instead of globally
1 parent 8f6bdf3 commit 355e866

File tree

5 files changed

+218
-136
lines changed

5 files changed

+218
-136
lines changed

src/core/query.ts

Lines changed: 18 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ export interface QueryState<TResult, TError> {
4444
isFetchingMore: IsFetchingMoreValue
4545
isIdle: boolean
4646
isLoading: boolean
47-
isStale: boolean
4847
isSuccess: boolean
4948
status: QueryStatus
5049
throwInErrorBoundary?: boolean
@@ -66,7 +65,6 @@ export interface RefetchOptions {
6665

6766
export enum ActionType {
6867
Failed = 'Failed',
69-
MarkStale = 'MarkStale',
7068
Fetch = 'Fetch',
7169
Success = 'Success',
7270
Error = 'Error',
@@ -76,10 +74,6 @@ interface FailedAction {
7674
type: ActionType.Failed
7775
}
7876

79-
interface MarkStaleAction {
80-
type: ActionType.MarkStale
81-
}
82-
8377
interface FetchAction {
8478
type: ActionType.Fetch
8579
isFetchingMore?: IsFetchingMoreValue
@@ -89,7 +83,6 @@ interface SuccessAction<TResult> {
8983
type: ActionType.Success
9084
data: TResult | undefined
9185
canFetchMore?: boolean
92-
isStale: boolean
9386
}
9487

9588
interface ErrorAction<TError> {
@@ -101,7 +94,6 @@ export type Action<TResult, TError> =
10194
| ErrorAction<TError>
10295
| FailedAction
10396
| FetchAction
104-
| MarkStaleAction
10597
| SuccessAction<TResult>
10698

10799
// CLASS
@@ -136,7 +128,6 @@ export class Query<TResult, TError> {
136128

137129
activateTimeouts(): void {
138130
this.enableTimeouts = true
139-
this.rescheduleStaleTimeout()
140131
this.rescheduleGarbageCollection()
141132
}
142133

@@ -150,45 +141,6 @@ export class Query<TResult, TError> {
150141
this.notifyGlobalListeners(this)
151142
}
152143

153-
private rescheduleStaleTimeout(): void {
154-
if (isServer) {
155-
return
156-
}
157-
158-
this.clearStaleTimeout()
159-
160-
if (
161-
!this.enableTimeouts ||
162-
this.state.isStale ||
163-
this.state.status !== QueryStatus.Success ||
164-
this.config.staleTime === Infinity
165-
) {
166-
return
167-
}
168-
169-
const staleTime = this.config.staleTime || 0
170-
let timeout = staleTime
171-
if (this.state.updatedAt) {
172-
const timeElapsed = Date.now() - this.state.updatedAt
173-
const timeUntilStale = staleTime - timeElapsed
174-
timeout = Math.max(timeUntilStale, 0)
175-
}
176-
177-
this.staleTimeout = setTimeout(() => {
178-
this.invalidate()
179-
}, timeout)
180-
}
181-
182-
invalidate(): void {
183-
this.clearStaleTimeout()
184-
185-
if (this.state.isStale) {
186-
return
187-
}
188-
189-
this.dispatch({ type: ActionType.MarkStale })
190-
}
191-
192144
private rescheduleGarbageCollection(): void {
193145
if (isServer) {
194146
return
@@ -230,7 +182,7 @@ export class Query<TResult, TError> {
230182

231183
private clearTimersObservers(): void {
232184
this.observers.forEach(observer => {
233-
observer.clearRefetchInterval()
185+
observer.clearTimers()
234186
})
235187
}
236188

@@ -264,20 +216,15 @@ export class Query<TResult, TError> {
264216
data = prevData
265217
}
266218

267-
const isStale = this.config.staleTime === 0
268-
269219
// Try to determine if more data can be fetched
270220
const canFetchMore = hasMorePages(this.config, data)
271221

272222
// Set data and mark it as cached
273223
this.dispatch({
274224
type: ActionType.Success,
275225
data,
276-
isStale,
277226
canFetchMore,
278227
})
279-
280-
this.rescheduleStaleTimeout()
281228
}
282229

283230
clear(): void {
@@ -293,12 +240,23 @@ export class Query<TResult, TError> {
293240
return this.observers.some(observer => observer.config.enabled)
294241
}
295242

243+
isStale(): boolean {
244+
return this.observers.some(observer => observer.isStale())
245+
}
246+
247+
isStaleByTime(staleTime = 0): boolean {
248+
return (
249+
!this.state.isSuccess || this.state.updatedAt + staleTime <= Date.now()
250+
)
251+
}
252+
296253
onWindowFocus(): void {
297254
if (
298-
this.state.isStale &&
299255
this.observers.some(
300256
observer =>
301-
observer.config.enabled && observer.config.refetchOnWindowFocus
257+
observer.isStale() &&
258+
observer.config.enabled &&
259+
observer.config.refetchOnWindowFocus
302260
)
303261
) {
304262
this.fetch()
@@ -308,10 +266,11 @@ export class Query<TResult, TError> {
308266

309267
onOnline(): void {
310268
if (
311-
this.state.isStale &&
312269
this.observers.some(
313270
observer =>
314-
observer.config.enabled && observer.config.refetchOnReconnect
271+
observer.isStale() &&
272+
observer.config.enabled &&
273+
observer.config.refetchOnReconnect
315274
)
316275
) {
317276
this.fetch()
@@ -628,12 +587,6 @@ function getDefaultState<TResult, TError>(
628587

629588
const hasInitialData = typeof initialData !== 'undefined'
630589

631-
const isStale =
632-
!config.enabled ||
633-
(typeof config.initialStale === 'function'
634-
? config.initialStale()
635-
: config.initialStale ?? !hasInitialData)
636-
637590
const initialStatus = hasInitialData
638591
? QueryStatus.Success
639592
: config.enabled
@@ -647,9 +600,8 @@ function getDefaultState<TResult, TError>(
647600
isFetching: initialStatus === QueryStatus.Loading,
648601
isFetchingMore: false,
649602
failureCount: 0,
650-
isStale,
651603
data: initialData,
652-
updatedAt: hasInitialData ? Date.now() : 0,
604+
updatedAt: Date.now(),
653605
canFetchMore: hasMorePages(config, initialData),
654606
}
655607
}
@@ -664,11 +616,6 @@ export function queryReducer<TResult, TError>(
664616
...state,
665617
failureCount: state.failureCount + 1,
666618
}
667-
case ActionType.MarkStale:
668-
return {
669-
...state,
670-
isStale: true,
671-
}
672619
case ActionType.Fetch:
673620
const status =
674621
typeof state.data !== 'undefined'
@@ -687,7 +634,6 @@ export function queryReducer<TResult, TError>(
687634
...getStatusProps(QueryStatus.Success),
688635
data: action.data,
689636
error: null,
690-
isStale: action.isStale,
691637
isFetched: true,
692638
isFetching: false,
693639
isFetchingMore: false,
@@ -703,7 +649,6 @@ export function queryReducer<TResult, TError>(
703649
isFetched: true,
704650
isFetching: false,
705651
isFetchingMore: false,
706-
isStale: true,
707652
failureCount: state.failureCount + 1,
708653
throwInErrorBoundary: true,
709654
}

src/core/queryCache.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ export class QueryCache {
189189
}
190190
}
191191

192-
return query.invalidate()
192+
return undefined
193193
})
194194
)
195195
} catch (err) {
@@ -305,7 +305,7 @@ export class QueryCache {
305305
let query
306306
try {
307307
query = this.buildQuery<TResult, TError>(queryKey, configWithoutRetry)
308-
if (options?.force || query.state.isStale) {
308+
if (options?.force || query.isStaleByTime(config.staleTime)) {
309309
await query.fetch()
310310
}
311311
return query.state.data

0 commit comments

Comments
 (0)