title: onReceive in SwiftUI view causes infinite loop
body: <p>In a SwiftUI app, I have an <code>ObservableObject</code> that keeps track of user settings:</p>
  
  <pre><code>class UserSettings: ObservableObject {
      @Published var setting: String?
  }
  </code></pre>
  
  <p>I have a view model to control the state for my view:</p>
  
  <pre><code>class TestViewModel: ObservableObject {
      @Published var state: String = ""
  }
  </code></pre>
  
  <p>And I have my view. When the user setting changes, I want to get the view model to update the state of the view:</p>
  
  <pre><code>struct HomeView: View {
      @EnvironmentObject var userSettings: UserSettings
      @ObservedObject var viewModel = TestViewModel()
  
      var body: some View {
          Text(viewModel.state)
              .onReceive(userSettings.$setting) { setting in
                  self.viewModel.state = setting
              }
      }
  }
  </code></pre>
  
  <p>When the <code>UserSettings.setting</code> is changed in another view it causes <code>onReceive</code> on my view to get called in an infinite loop, and I don't understand why. I saw <a href="https://stackoverflow.com/questions/60617914/onreceive-string-publisher-lead-to-infinite-loop">this question</a>, and that loop makes sense to me because the state of the <code>ObservableObject</code> being observed is being changed on observation.</p>
  
  <p>However, in my case I'm not changing the observed object (environment object) state. I'm observing the environment object and changing the view model state which redraws the view.</p>
  
  <p>Is the view redrawing what's causing the issue here? Does <code>onReceive</code> get called everytime the view is redrawn?</p>
  
  <p>Is there a better way of accomplishing what I'm trying to do?</p>
  
  <p><strong>EDIT</strong>: this is a greatly simplified version of my problem. In my app, the view model takes care of executing a network request based on the user's settings and updating the view's state such as displaying an error message or loading indicator. </p>