8

Is there any way to prevent onReceive from firing when the view initially loads when the variable I'm trying to receive is a @Published property of an @EnvironmentObject?

Here's the view:

struct ContentView: View {
    @EnvironmentObject var appState: AppState
    
    var body: some View {
        VStack {
            Text(appState.test)
                .padding()
        }
        .onAppear() {
            appState.test = "World"
        }
        .onReceive(appState.$test) { test in
            print("Hello from onReceive: \(test)")
        }
    }
}

Here's the environment object:

public class AppState: ObservableObject {
    @Published public var test = "hello"
}

And output:

Hello from onReceive: hello
Hello from onReceive: World

I'm guessing the first one is fired when the environment object is injected. Is there any way to prevent this (other than some hackish bool that I set in the onAppear)? Ideally I'd like to only see "Hello from onReceive: World" This is just a simple example. On my actual app I am fetching data from a service in onAppear, in my environment object I have an error state that when cleared, I want it to fire the onReceive do some other logic then refetch.

Dennis Calla
  • 839
  • 9
  • 10

1 Answers1

14

It is publisher, so you can use any combine operators. In this case .dropFirst solves your task:

    .onReceive(appState.$test.dropFirst()) { test in
        print("Hello from onReceive: \(test)")
    }
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Asperi
  • 228,894
  • 20
  • 464
  • 690