Skip to content

Commit fafb2ce

Browse files
author
Hoang Pham
committed
Refactor options onChange
1 parent 112070f commit fafb2ce

5 files changed

Lines changed: 93 additions & 73 deletions

File tree

Example/swiftui-query-demo/ContentView.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,18 +121,19 @@ struct PokemonListView: View {
121121
var body: some View {
122122
WithPerceptionTracking {
123123
// Capture the initial offset value before the closures
124+
let initialOffset = self.initialOffset
124125
let capturedOffset = initialOffset
125126

126127
UseInfiniteQuery(
127128
queryKey: "pokemon-infinite-list-\(initialOffset)", // Include offset in key for cache separation
128129
queryFn: { _, pageParam in
129-
let offset = pageParam ?? capturedOffset
130-
return try await PokemonAPI.fetchPokemonPage(offset: offset)
130+
let offset = pageParam ?? initialOffset
131+
return try await PokemonAPI.fetchPokemonPage(offset: offset + capturedOffset)
131132
},
132133
getNextPageParam: { pages in
133134
// Calculate next offset based on current pages and initial offset
134135
let currentTotal = pages.reduce(0) { total, page in total + page.results.count }
135-
let nextOffset = capturedOffset + currentTotal
136+
let nextOffset = currentTotal
136137
let lastPage = pages.last
137138

138139
// If we have next URL or haven't reached the total count, continue pagination
@@ -141,7 +142,7 @@ struct PokemonListView: View {
141142
}
142143
return nil // No more pages
143144
},
144-
initialPageParam: capturedOffset,
145+
initialPageParam: 0,
145146
staleTime: 5 * 60 // 5 minutes before considered stale
146147
) { result in
147148
if result.isLoading, result.data?.pages.isEmpty != false {

Sources/SwiftUIQuery/InfiniteQuery.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public struct InfiniteQueryFetchMeta: Sendable {
5252
public struct InfiniteQueryConfig<
5353
TData: Sendable,
5454
TKey: QueryKey,
55-
TPageParam: Sendable & Codable
55+
TPageParam: Sendable & Codable & Equatable
5656
> {
5757
public let queryKey: TKey
5858
public let queryHash: String
@@ -84,7 +84,7 @@ public struct InfiniteQueryConfig<
8484
public final class InfiniteQuery<
8585
TData: Sendable,
8686
TKey: QueryKey,
87-
TPageParam: Sendable & Codable
87+
TPageParam: Sendable & Codable & Equatable
8888
>: AnyQuery, AnyInfiniteQuery {
8989
// MARK: - Public Properties
9090

Sources/SwiftUIQuery/InfiniteQueryObserver.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ public struct InfiniteQueryObserverResult<TData: Sendable, TPageParam: Sendable
130130
public final class InfiniteQueryObserver<
131131
TData: Sendable,
132132
TKey: QueryKey,
133-
TPageParam: Sendable & Codable
133+
TPageParam: Sendable & Codable & Equatable
134134
>: AnyQueryObserver, ObservableObject {
135135
// MARK: - Public Properties
136136

Sources/SwiftUIQuery/SwiftUIQuery.swift

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ public enum NetworkMode: String, Sendable, Codable {
253253

254254
/// Configuration for when to refetch queries in iOS/SwiftUI
255255
/// iOS-specific equivalent to TanStack Query's refetch triggers
256-
public struct RefetchTriggers: Sendable, Codable {
256+
public struct RefetchTriggers: Sendable, Codable, Equatable {
257257
/// Refetch when view appears (SwiftUI .onAppear)
258258
public let onAppear: Bool
259259
/// Refetch when app becomes active from background
@@ -273,7 +273,7 @@ public struct RefetchTriggers: Sendable, Codable {
273273

274274
/// Enum specifying when to refetch on view appear
275275
/// Maps to SwiftUI .onAppear behavior
276-
public enum RefetchOnAppear: Sendable, Codable {
276+
public enum RefetchOnAppear: Sendable, Codable, Equatable {
277277
/// Always refetch when view appears
278278
case always
279279
/// Only refetch if data is stale when view appears
@@ -421,8 +421,8 @@ public struct InfiniteQueryOptions<
421421
TData: Sendable,
422422
TError: Error & Sendable & Codable,
423423
TKey: QueryKey,
424-
TPageParam: Sendable & Codable
425-
>: Sendable {
424+
TPageParam: Sendable & Codable & Equatable
425+
>: Sendable, Equatable {
426426
/// The query key that uniquely identifies this query
427427
public let queryKey: TKey
428428
/// The function that will be called to fetch data pages
@@ -454,6 +454,20 @@ public struct InfiniteQueryOptions<
454454
/// Whether this query is enabled (will fetch automatically)
455455
public let enabled: Bool
456456

457+
public static func == (
458+
lhs: InfiniteQueryOptions<TData, TError, TKey, TPageParam>,
459+
rhs: InfiniteQueryOptions<TData, TError, TKey, TPageParam>
460+
) -> Bool {
461+
lhs.queryKey == rhs.queryKey &&
462+
lhs.initialPageParam == rhs.initialPageParam &&
463+
lhs.maxPages == rhs.maxPages &&
464+
lhs.staleTime == rhs.staleTime &&
465+
lhs.gcTime == rhs.gcTime &&
466+
lhs.refetchTriggers == rhs.refetchTriggers &&
467+
lhs.refetchOnAppear == rhs.refetchOnAppear &&
468+
lhs.enabled == rhs.enabled
469+
}
470+
457471
public init(
458472
queryKey: TKey,
459473
queryFn: @escaping InfiniteQueryFunction<TData, TKey, TPageParam>,

Sources/SwiftUIQuery/UseInfiniteQuery.swift

Lines changed: 67 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ public struct UseInfiniteQueryResult<TData: Sendable, TPageParam: Sendable & Cod
129129
public struct UseInfiniteQuery<
130130
TData: Sendable,
131131
TKey: QueryKey,
132-
TPageParam: Sendable & Codable,
132+
TPageParam: Sendable & Codable & Equatable,
133133
Content: View
134134
>: View {
135135
// MARK: - Private Properties
@@ -282,69 +282,74 @@ public struct UseInfiniteQuery<
282282
.onDisappear {
283283
observer.unsubscribe()
284284
}
285-
.onChange(of: options.queryKey) { newKey in
286-
let newOptions = InfiniteQueryOptions<TData, QueryError, TKey, TPageParam>(
287-
queryKey: newKey,
288-
queryFn: options.queryFn,
289-
getNextPageParam: options.getNextPageParam,
290-
getPreviousPageParam: options.getPreviousPageParam,
291-
initialPageParam: options.initialPageParam,
292-
maxPages: options.maxPages,
293-
retryConfig: options.retryConfig,
294-
networkMode: options.networkMode,
295-
staleTime: options.staleTime,
296-
gcTime: options.gcTime,
297-
refetchTriggers: options.refetchTriggers,
298-
refetchOnAppear: options.refetchOnAppear,
299-
structuralSharing: options.structuralSharing,
300-
meta: options.meta,
301-
enabled: options.enabled
302-
)
303-
observer.setOptions(newOptions)
304-
}
305-
.onChange(of: options.enabled) { newEnabled in
306-
// Update observer options when enabled state changes
307-
// Create new options using the new enabled value
308-
let newOptions = InfiniteQueryOptions<TData, QueryError, TKey, TPageParam>(
309-
queryKey: options.queryKey,
310-
queryFn: options.queryFn,
311-
getNextPageParam: options.getNextPageParam,
312-
getPreviousPageParam: options.getPreviousPageParam,
313-
initialPageParam: options.initialPageParam,
314-
maxPages: options.maxPages,
315-
retryConfig: options.retryConfig,
316-
networkMode: options.networkMode,
317-
staleTime: options.staleTime,
318-
gcTime: options.gcTime,
319-
refetchTriggers: options.refetchTriggers,
320-
refetchOnAppear: options.refetchOnAppear,
321-
structuralSharing: options.structuralSharing,
322-
meta: options.meta,
323-
enabled: newEnabled
324-
)
325-
observer.setOptions(newOptions)
326-
}
327-
.onChange(of: options.staleTime) { newStaleTime in
328-
// Update observer options when staleTime changes
329-
let newOptions = InfiniteQueryOptions<TData, QueryError, TKey, TPageParam>(
330-
queryKey: options.queryKey,
331-
queryFn: options.queryFn,
332-
getNextPageParam: options.getNextPageParam,
333-
getPreviousPageParam: options.getPreviousPageParam,
334-
initialPageParam: options.initialPageParam,
335-
maxPages: options.maxPages,
336-
retryConfig: options.retryConfig,
337-
networkMode: options.networkMode,
338-
staleTime: newStaleTime,
339-
gcTime: options.gcTime,
340-
refetchTriggers: options.refetchTriggers,
341-
refetchOnAppear: options.refetchOnAppear,
342-
structuralSharing: options.structuralSharing,
343-
meta: options.meta,
344-
enabled: options.enabled
345-
)
285+
.onChange(of: options) { newOptions in
346286
observer.setOptions(newOptions)
347287
}
288+
// .onChange(of: options.enabled) { newEnabled in
289+
// // Update observer options when enabled state changes
290+
// // Create new options using the new enabled value
291+
// let newOptions = InfiniteQueryOptions<TData, QueryError, TKey, TPageParam>(
292+
// queryKey: options.queryKey,
293+
// queryFn: options.queryFn,
294+
// getNextPageParam: options.getNextPageParam,
295+
// getPreviousPageParam: options.getPreviousPageParam,
296+
// initialPageParam: options.initialPageParam,
297+
// maxPages: options.maxPages,
298+
// retryConfig: options.retryConfig,
299+
// networkMode: options.networkMode,
300+
// staleTime: options.staleTime,
301+
// gcTime: options.gcTime,
302+
// refetchTriggers: options.refetchTriggers,
303+
// refetchOnAppear: options.refetchOnAppear,
304+
// structuralSharing: options.structuralSharing,
305+
// meta: options.meta,
306+
// enabled: newEnabled
307+
// )
308+
// observer.setOptions(newOptions)
309+
// }
310+
// .onChange(of: options.initialPageParam) { newInitialPageParam in
311+
// // Update observer options when enabled state changes
312+
// // Create new options using the new enabled value
313+
// let newOptions = InfiniteQueryOptions<TData, QueryError, TKey, TPageParam>(
314+
// queryKey: options.queryKey,
315+
// queryFn: options.queryFn,
316+
// getNextPageParam: options.getNextPageParam,
317+
// getPreviousPageParam: options.getPreviousPageParam,
318+
// initialPageParam: newInitialPageParam,
319+
// maxPages: options.maxPages,
320+
// retryConfig: options.retryConfig,
321+
// networkMode: options.networkMode,
322+
// staleTime: options.staleTime,
323+
// gcTime: options.gcTime,
324+
// refetchTriggers: options.refetchTriggers,
325+
// refetchOnAppear: options.refetchOnAppear,
326+
// structuralSharing: options.structuralSharing,
327+
// meta: options.meta,
328+
// enabled: options.enabled
329+
// )
330+
// observer.setOptions(newOptions)
331+
// }
332+
// .onChange(of: options.staleTime) { newStaleTime in
333+
// // Update observer options when staleTime changes
334+
// let newOptions = InfiniteQueryOptions<TData, QueryError, TKey, TPageParam>(
335+
// queryKey: options.queryKey,
336+
// queryFn: options.queryFn,
337+
// getNextPageParam: options.getNextPageParam,
338+
// getPreviousPageParam: options.getPreviousPageParam,
339+
// initialPageParam: options.initialPageParam,
340+
// maxPages: options.maxPages,
341+
// retryConfig: options.retryConfig,
342+
// networkMode: options.networkMode,
343+
// staleTime: newStaleTime,
344+
// gcTime: options.gcTime,
345+
// refetchTriggers: options.refetchTriggers,
346+
// refetchOnAppear: options.refetchOnAppear,
347+
// structuralSharing: options.structuralSharing,
348+
// meta: options.meta,
349+
// enabled: options.enabled
350+
// )
351+
// observer.setOptions(newOptions)
352+
// }
348353
}
349354
}
350355

0 commit comments

Comments
 (0)