Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to invalidate and refetch query? #15

Closed
acoustep opened this issue Nov 19, 2020 · 2 comments
Closed

How to invalidate and refetch query? #15

acoustep opened this issue Nov 19, 2020 · 2 comments
Labels
question Further information is requested

Comments

@acoustep
Copy link

Hi!

Thanks for this great library. I have it mostly working, but I'm struggling with one issue.

I'm trying to invalidate and refetch data when a user does an action. I can see there is a way to do with this with mutations in the docs but I can't seem to do it with a Query.

I have tried using UserDefaultsQueryCache.shared.invalidate(for:), but nothing seems to happen.

Here's what I have so far, I'm using a pull down library which I'm trying to trigger the refresh.

import SwiftUI
import Combine
import Pigeon
import SwiftUIRefresh

struct UnreadView: View {
    @State private var showPull = false
    private var queryInvalidator = UserDefaultsQueryCache.shared
    
    @ObservedObject var query = Query<Void, [Pin]>(
            key: QueryKey(value: "all"),
            behavior: .startWhenRequested,
            cache: UserDefaultsQueryCache.shared,
            cacheConfig: QueryCacheConfig(
                invalidationPolicy: .expiresAfter(1000),
                usagePolicy: .useInsteadOfFetching
            ),
            fetcher: {
                print("FETCHING All Pins")
                return GetAllPinsRequest()
                    .execute()
                    .map { return $0}
                    .eraseToAnyPublisher()
            }
        )
    
    var unreadPins: [Pin] {
        switch query.state {
        case .succeed(let pins):
            return pins.filter { pin in
                return pin.toRead == "yes"
            }
        default:
            return []
        }
    }
    
    var body: some View {
        view(for: query.state)
            .navigationTitle("Unread")
            .onAppear(perform: {
                query.refetch(request: ())
            })
            .pullToRefresh(isShowing: $showPull) {
                  queryInvalidator.invalidate(for: QueryKey(value: "all"))
                  query.refetch(request: ())
                 DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                    self.showPull = false
                }
            }
    }
}

extension UnreadView: QueryRenderer {
    var loadingView: some View {
        Text("Loading...")
    }
    
    func successView(for pins: [Pin]) -> some View {
        List(unreadPins) { pin in
            NavigationLink(destination: PinPreviewView(title: pin.title, url: pin.url)) {
                VStack(alignment: .leading, spacing: 10) {
                    Text("\(pin.title)").font(.headline)
                    Text("\(pin.url)").lineLimit(1).truncationMode(.tail)
                    TagListView(tags: pin.tags)
                }.padding(.vertical)
            }
        }.listStyle(InsetGroupedListStyle())
    }
    
    func failureView(for failure: DecodingError) -> some View {
        Text("Error loading pins")
    }
    func failureView(for failure: Error) -> some View {
        Text("Error")
           
    }
}

Thanks for any guidance you can give.

@fmo91
Copy link
Owner

fmo91 commented Nov 23, 2020

Hi @acoustep . First of all, thanks for using this lib in your project. It really means a lot to me!
Well, about it... I should have made the init in QueryInvalidator public, but I didn't. If you update Pigeon to 0.1.17, you'll be capable of doing something like this:

import SwiftUI
import Combine
import Pigeon

struct ContentView: View {
    @StateObject private var queryA = Query<Void, String>(
        key: .keyA,
        fetcher: {
            Just("A")
                .mapError { $0 }
                .handleEvents(receiveOutput: { (value: String) in
                    print("Received value from queryA", value)
                })
                .eraseToAnyPublisher()
        }
    )
    
    @StateObject private var queryB = Query<Void, String>(
        key: .keyB,
        fetcher: {
            Just("B")
                .mapError { $0 }
                .handleEvents(receiveOutput: { (value: String) in
                    print("Received value from queryB", value)
                })
                .eraseToAnyPublisher()
        }
    )
    
    var body: some View {
        VStack {
            Button("Query A", action: {
                queryA.refetch(request: ())
            })
            
            Button("Query B", action: {
                queryB.refetch(request: ())
            })
            
            Button("Invalidate Query A", action: {
                QueryInvalidator()
                    .invalidateQuery(for: .keyA, with: .lastData)
            })
            
            Button("Invalidate Query B", action: {
                QueryInvalidator()
                    .invalidateQuery(for: .keyB, with: .lastData)
            })
        }
    }
}

extension QueryKey {
    static var keyA: QueryKey { .init(value: "A") }
    static var keyB: QueryKey { .init(value: "B") }
}

Using QueryInvalidator you can invalidate QueryKey elements either with the last data used, or sending new input for those queries.
Let me know if this works for you!

@fmo91
Copy link
Owner

fmo91 commented Nov 23, 2020

I'll close this issue. If you have any other problem, please let me know and I can reopen it! Thanks!

@fmo91 fmo91 closed this as completed Nov 23, 2020
@fmo91 fmo91 added enhancement New feature or request question Further information is requested and removed enhancement New feature or request labels Nov 23, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants