Why does this not work

I have an app that depends on a model which displays quite different screens depending on current state. Here’s a simple minimum example WHICH WORKS to illustrate the idea. The model is observed via @StateObject and the ContentView() simply switches on state.

In my real model, each display is more complex so it makes sense to drop them into separate structs, but when I do, they seem to lose track of state. This is also illustrated below in my very simple example. What am I doing wrong?

Working Version of ContentView()

struct ContentView: View {
   @StateObject var viewModel = ViewModel()

   var body: some View {
      Group {
         switch viewModel.state {
            case .A: VStack {
               Text("Showing A")
               Button("Change") {
                  viewModel.changeState(.B)
               }
            }
            case .B: VStack {
               Text("Showing B")
               Button("Change") {
                  viewModel.changeState(.C)
               }
            }
            case .C: VStack {
               Text("Showing C")
               Button("Change") {
                  viewModel.changeState(.A)
               }
            }
         }
      }.environmentObject(viewModel)
   }
}

Broken Version of ContentView()

struct ContentView: View {
   @StateObject var viewModel = ViewModel()

   var body: some View {
      Group {
         switch viewModel.state {
            case .A: AView()
            case .B: BView()
            case .C: CView()
         }
      }.environmentObject(viewModel)
   }
}

struct AView: View {
   @StateObject var viewModel = ViewModel()

   var body: some View {
      VStack {
         Text("Showing A")
         Button("Change") {
            viewModel.changeState(.B)
         }
      }
   }
}

struct BView: View {
   @StateObject var viewModel = ViewModel()
   
   var body: some View {
      VStack {
         Text("Showing B")
         Button("Change") {
            viewModel.changeState(.C)
         }
      }
   }
}

struct CView: View {
   @StateObject var viewModel = ViewModel()
   
   var body: some View {
      VStack {
         Text("Showing C")
         Button("Change") {
            viewModel.changeState(.A)
         }
      }
   }
}

The Model and the ViewModel:

struct Model {
   var state:State = .A
}

enum State: String {
   case A
   case B
   case C
}

class ViewModel: ObservableObject {
   @Published var model = Model()
   var state: State { return model.state }
   
   func changeState(_ state: State) {
      model.state = state
   }
}

hi Don, to use an environment object in your subviews, declare it as @EnvironmentObject not @StateObject, and don’t reinitialise it:

@EnvironmentObject var history: HistoryStore

Thanks Audrey
Sorry … elementary error. However, I didn’t make this error in my real app so I’ve failed to capture the essence of what’s going on in my simplified one. Back to the drawing board!
Tchelyzt

Have you figured out where the problem is?

If not, is it possible that you’re triggering the update from a background thread, or from a view that’s not in the hierarchy of the view which should be affected by the change?

Hello Jeden,
yes thanks. Sorted it out
Tchelyzt