Downloading an array of data and then drilling down to children (which have to be downloaded)

I feel like I've done this before but I'm suffering from mental block.

I currently have state like...

// AccountsCore
struct State {
  var accounts: IdentifiedArrayOf<Account>? = nil
}

And an endpoint which downloads that array and stores it in state which then updates the view and everything is good. Now we need to drill down into that data and view details about the account.

However, the endpoint I get for the list only returns surface level details (title, description). So, when I drill down into each Account I need to hit another endpoint to get the AccountDetails which shows all the bits I need to display in the next screen.

I have state for the AccountDetail like...

// AccountDetailCore
struct State {
  let accountId: String
  var details: AccountDetail? = nil

  init(accountId: String) {
    self.accountId = accountId
  }
}

And again, this has an endpoint that gets hit with the accountId and returns the required data and updates the view.

I'm just having a complete brain fog around connecting these up?

Current implementation (not optimal)

For now I've just got a @BindableState var accountDetailState: AccountDetail.State? = nil and I'm using the .isPresent() to drive the navigation to it. But that's not ideal because each time you navigate back we're throwing away all the data that we previously had downloaded.

Nest the data?

Would it be better to nest the AccountDetail as a property of Account? So that way my accounts array in the parent state would be holding on to all child state too?

Store a separate array?

Should I store a second array like accountDetails: IdentifiedArrayOf<AccountDetail.State>? And use that to hold onto the state without nesting?

How to scope the Reducer?

If I store the AccountDetail INSIDE the Account so it's nested I'd need to use a Scope and a ForEach to scope the Reducer I think?

Something like...

// AccountsCore reducer
enum Action {
  case accountDetail(AccountId, AccountDetail.Action)
}

Reducer{ state, action in ... }
  .forEach(\.openedProducts, action: /Action...?) {
    Scope(state: \.accountDetail, action: /Action...?) {
      AccountDetailCore()
    }
  }

How would I scope the action here? I really only need one scope from Account.Action to AccountDetail.Action.

Hmm...

Hmm... maybe I'm thinking about this wrong.

I could instead store an array of AccountDetailCore.State and use that to hold the surface level Account.

That would make things easier and mean I don't have to add nesting to what is essentially the network models.

So transform the network models into State structs which work for me.

Actually... this isn't a good path to go down. It starts to pollute the child state with parent state. So the child becomes less reusable.

OK... I turned this around on it's head and got it working I think.

Will test tomorrow. :smiley: