title: SwiftUI nested LazyVStacks in a single ScrollView
body: <p>I'm trying to build a comment thread. So top level comments can all have nested comments and so can they and so on and so forth. But I'm having issues around scrolling and also sometimes when expanding sections the whole view just jumps around, and can have a giant blank space at the bottom. The code looks like this:</p>
  <pre class="lang-swift prettyprint-override"><code>struct ContentView: View {
      
      var body: some View {
          VStack {
              HStack {
                  Text(&quot;Comments&quot;)
                      .font(.system(size: 34))
                      .fontWeight(.bold)
                  Spacer()
              }
              .padding()
              CommentListView(commentIds: [0, 1, 2, 3], nestingLevel: 1)
          }
      }
      
  }
  
  struct CommentListView: View {
  
      let commentIds: [Int]?
      let nestingLevel: Int
  
      var body: some View {
          if let commentIds = commentIds {
              LazyVStack(alignment: .leading) {
                  ForEach(commentIds, id: \.self) { id in
                      CommentItemView(viewModel: CommentItemViewModel(commentId: id), nestingLevel: nestingLevel)
                  }
              }
              .applyIf(nestingLevel == 1) {
                  $0.scrollable()
              }
          } else {
              Spacer()
              Text(&quot;No comments&quot;)
              Spacer()
          }
      }
      
  }
  
  struct CommentItemView: View {
      
      @StateObject var viewModel: CommentItemViewModel
      let nestingLevel: Int
      @State private var showComments = false
      
      var body: some View {
          VStack {
              switch viewModel.viewState {
              case .error:
                  Text(&quot;Error&quot;)
                      .fontWeight(.thin)
                      .font(.system(size: 12))
                      .italic()
              case .loading:
                  Text(&quot;Loading&quot;)
                      .fontWeight(.thin)
                      .font(.system(size: 12))
                      .italic()
              case .complete:
                  VStack {
                      Text(viewModel.text)
                          .padding(.bottom)
                          .padding(.leading, 20 * CGFloat(nestingLevel))
                      if let commentIds = viewModel.commentIds {
                          Button {
                              withAnimation {
                                  showComments.toggle()
                              }
                          } label: {
                              Text(showComments ? &quot;Hide comments&quot; : &quot;Show comments&quot;)
                          }
                          if showComments {
                              CommentListView(commentIds: commentIds, nestingLevel: nestingLevel + 1)
                          }
                      }
                  }
              }
          }
      }
  }
  
  class CommentItemViewModel: ObservableObject {
  
      @Published private(set) var text = &quot;&quot;
      @Published private(set) var commentIds: [Int]? = [0, 1, 2, 3]
      @Published private(set) var viewState: ViewState = .loading
      private let commentId: Int
  
      private var viewStateInternal: ViewState = .loading {
          willSet {
              withAnimation {
                  viewState = newValue
              }
          }
      }
  
      init(commentId: Int) {
          self.commentId = commentId
          fetchComment()
      }
  
      private func fetchComment() {
          viewStateInternal = .complete
          text = CommentValue.allCases[commentId].rawValue
      }
  
  }
  </code></pre>
  <p>Has anyone got a better way of doing this? I know <code>List</code> can now accept a KeyPath to child object and it can nest that way, but there's so limited design control over <code>List</code> that I didn't want to use it. Also, while this code is an example, the real code will have to load each comment from an API call, so <code>List</code> won't perform as well as <code>LazyVStack</code> in that regard.</p>
  <p>Any help appreciated - including a complete overhaul of how to implement this sort of async loading nested view.</p>