How to scope and pullback a single identified element?

I'm not sure in this situation how I should be pulling the state back. I've got two sets of arrays, one of 'things1' and one of 'things2'.

public struct DemoState: Equatable {
    var things1: IdentifiedArrayOf<ThingState> = [ ThingState(data: "Label1"), ThingState(data: "Label2") ]
    var things2: IdentifiedArrayOf<ThingState> = [ ThingState(data: "Data1"), ThingState(data: "Data2") ]
}

In my view, I want to iterate over the first array so that I can present NavigationLinks to a child view that shows one of thing1's and all of things2 (Thing12View):

ForEach(viewStore.things1, id: \.id) { thing in

    NavigationLink(
        destination:
            Thing12View(store: self.store.scope(
                state: {
                    Thing12ViewState(
                        thing: thing,
                        things2: $0.things2
                    )
                },
                action: { DemoAction.thing12(id: thing.id, action: $0) }
            )),
        label: {
            Thing1View(store: self.store.scope(
                state: { _ in thing },
                action: DemoAction.thing
            ))
        }
    )
    
}

But I'm struggling with the correct set of reducers to pull my state back. As it stands, my state isn't updating properly. I think I need a way to pullback my Thing12ViewState. Alternatively, perhaps I shouldn't be scoping a single array element in this way.

Another way to ask the question more simply: How do I send down and then pullback a single Identified item from my IdentifiedArray in the global state?

Sample project: https://www.dropbox.com/s/qjptguq3tqu7gom/foreach-nested_data.zip?dl=1

In case anyone is interested, the solution was to map the actions correctly from the Thing12View back up to the parent view's index'ed actions so the .forEach reducers could do their thing properly:

Replacing this:

action: { DemoAction.thing12(id: thing.id, action: $0) }

with this:

action: { thing12ViewAction in
    switch thing12ViewAction {
        case Thing12ViewAction.thing(let action):
            return DemoAction.thing1(id: thing.id, action: action)
        
        case Thing12ViewAction.thing2(id: let id, action: let action):
            return DemoAction.thing2(id: id, action: action)
    }
}

Final working project: https://www.dropbox.com/s/2doluou6p4iudut/foreach-nested_data-working.zip?dl=1

2 Likes

As a final follow-up, I ended up refactoring it one more time to be more like the 03-Navigation-Lists-NavigateAndLoad TCA demo and I used an optional Identified property

    var selection: Identified<ThingState.ID, ThingsViewState>?

which ended up working much better and made for less and cleaner code.

1 Like