I've got a view that scopes down a collection of IdentifiedArray items to a single item.
In that view, the user can choose to delete the item, but since I don't have access to the full array there, I'd have to handle it in a higher order reducer. This is an often re-used view, and ideally I wouldn't have every parent have to manage removing it from the array if the user chooses to delete.
Interesting, I'm working on the same problem. I still have not come up with the ideal approach but one way to do this is create a 'Crud Action'. (okay there is no 'read' in this CRUD) The idea is that the update case is handling what TCA's Reducer.forEach does. but you can also bake in the list level actions (create, delete, swap, moveToFront, etc..) as well.
enum CrudAction<Entity, SubAction, ID: Hashable> {
case create(ID)
case update(ID, SubAction)
case remove(ID)
}
you can write a higher order reducer like Reducer.forEach to also handle the generic cases of list manipulation as well as the element case (update).
note: i'm leaning towards this being a bad idea. it begins to looses the clean separation between the collection structure and the element in isolation. i'd much prefer to compose this with a generic list reducer at the parent view level. the problem is sometimes the element view wants to communicate actions back up that relate to the collection structure its embedded in.
Right now, I'm running two reducers, in pseudocode:
let arrayReducer: Reducer<...> = .combine(
itemReducer.forEach(...),
Reducer { state, action, env in
case .item(id: let id, action: let action):
switch action {
case .update:
// update db
case .delete:
// delete child from my parent array
// delete child in DB
}
}
)
I'd still like this a bit more generic, but so far this allows the child to update its local state as far as it can, then this parent reducer will remove it from the array (in the case of delete) as well as update the DB as needed.
What I still haven't fully internalized is how I'd create a generic version of that second reducer, given that each parent action type would be different.
i would imagine // update the db also happens in the forEach. but creating a reducer for [T] structure is easy enough. its the effects that pose a problem. could you write a reducer over [T: DBItem] where DBItem is a protocol that specifies Effect's for the common CRUD operations? A concrete DBItem could return e.g. "Core Data Remove Effect" for .removeEffect. anyway, you could then fully write listReducer<Element: DBItem>, no?