Pigeon icon indicating copy to clipboard operation
Pigeon copied to clipboard

Include @ViewBuilder in state switch in the Readme

Open dehlen opened this issue 3 years ago • 7 comments

In your readme the following sample code is shown:


// ...
    var body: some View {
        // 5
        switch users.state {
            case .idle, .loading:
                return AnyView(Text("Loading..."))
            case .failed:
                return AnyView(Text("Oops..."))
            case let .succeed(users):
                return AnyView(
                    List(users) { user in
                        Text(user.name)
                    }
                )
        }
    }

As far as I can see you can use the ViewBuilder feature in this case. The QueryRenderer protocol of course is useful too but this would make the code a little but more readable imo and provides another alternative for your users:


// ...
    @ViewBuilder var body: some View {
        // 5
        switch users.state {
            case .idle, .loading:
                Text("Loading...")
            case .failed:
                Text("Oops...")
            case let .succeed(users):
                List(users) { user in
                    Text(user.name)
                }
        }
    }

Please also note that @ViewBuilder is automatically added to the body on iOS 14.

dehlen avatar Sep 04 '20 17:09 dehlen

Hi @dehlen , thank you for making this suggestion! Wow, that makes the code way more readable for sure. To be honest, I haven't used it before. I'll test it later today and fix it in the README.md

fmo91 avatar Sep 04 '20 17:09 fmo91

I've also changed the title to make it clearer in my opinion. Thank you!

fmo91 avatar Sep 04 '20 17:09 fmo91

No problem glad if this helps :) I just removed the return keyword as well since I think it is not needed/wrong when using ViewBuilders. I typed all of this on my phone so let me know if something does not work for you and I‘ll take a look.

dehlen avatar Sep 04 '20 18:09 dehlen

Hi @dehlen . I've been testing it. Unfortunately, it doesn't work for me. Am I doing something wrong? This is my code:

import SwiftUI
import Pigeon

struct ContentView: View {
    @ObservedObject private var users = Query<Void, [User]>.init(
        key: .users,
        behavior: .startImmediately(()),
        fetcher: {
            URLSession.shared
                .dataTaskPublisher(for: URL(string: "https://jsonplaceholder.typicode.com/users")!)
                .map(\.data)
                .decode(type: [User].self, decoder: JSONDecoder())
                .receive(on: DispatchQueue.main)
                .eraseToAnyPublisher()
        }
    )
    
    @ViewBuilder var body: some View {
        // 5
        switch users.state {
            case .idle, .loading:
                Text("Loading...")
            case .failed:
                Text("Oops...")
            case let .succeed(users):
                List(users) { user in
                    Text(user.name)
                }
        }
    }
}

extension QueryKey {
    static var users: QueryKey { .init(value: "users") }
}

struct User: Codable, Identifiable {
    let id: Int
    let name: String
}

If you could send something like this, an autocontained piece of code that actually works (not like mine), I'll test it and fix it in the README.md.

Thank you!

fmo91 avatar Sep 06 '20 15:09 fmo91

Your example just compiles and runs fine for me. I am using Xcode 12 beta 5 currently.

dehlen avatar Sep 07 '20 06:09 dehlen

Maybe that's it, I'm using Xcode 11.7

fmo91 avatar Sep 07 '20 12:09 fmo91

I'll test it in Xcode 12 and fix the readme. I should also do that to replace @ObservedObject with @StateObject

fmo91 avatar Sep 07 '20 13:09 fmo91