Replies: 1 comment
-
Well, by rereading the TreeBasedNavigation article I think I got the model sorted out: struct ThingPicker <T: Equatable & Identifiable>: Reducer {
struct State: Equatable {
var things: [T]
var filterString: String = ""
}
enum Action {
case setFilter(String)
case thingSelected(T)
case cancelClicked
}
@Dependency(\.dismiss) var dismiss
var body: some ReducerOf<Self> {
return Reduce<State, Action> { state, action in
switch action {
case let .setFilter(filter):
state.filterString = filter
return .none
case .thingSelected: // <--- this is the one the parent will care about
return .none
case .cancelClicked:
return .run { _ in await self.dismiss() }
}
}
}
}
struct EditPerson: Reducer {
struct PersonPicker: Reducer {
enum State: Equatable { // <--- this needs to be true so that the view can observe the state
case parent(ThingPicker<Person>.State)
case partner(ThingPicker<Person>.State)
case child(ThingPicker<Person>.State)
}
enum Action {
case parent(ThingPicker<Person>.Action)
case partner(ThingPicker<Person>.Action)
case child(ThingPicker<Person>.Action)
}
var body: some ReducerOf<Self> {
Scope(state: /State.parent, action: /Action.parent) {
ThingPicker<Person>()
}
Scope(state: /State.partner, action: /Action.partner) {
ThingPicker<Person>()
}
Scope(state: /State.child, action: /Action.child) {
ThingPicker<Person>()
}
}
}
struct State: Equatable {
var person: Person?
var population: Population
@PresentationState var picker: PersonPicker.State? // <-- to make the state equatable, the PersonPicker.State has to be.
}
enum Action {
// ... unchanged from above
case addParentPressed
case addPartnerPressed
case addChildPressed
case picker(PresentationAction<PersonPicker.Action>)
}
var body: some ReducerOf<Self> {
Reduce<State, Action> { state, action in
switch action {
// ...
case .addParentPressed:
guard let person = state.person else { return .none }
// limit the picker to show people who aren't already this person's parent or this person
state.picker = .parent(.init(things: state.population.people.filter({ candidate in
candidate.id != person.id && !person.parents.contains(where: { candidate.id == $0 })
})))
return .none
case let .picker(.presented(.parent(.thingSelected(parent)))):
state.picker = nil // <-- dismiss the picker by clearing out the state
// ...perform data updates, linking the person and the selected parent
// ...
}
} |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I'll start with the desired user experience to provide context, but then what I'm really looking for is a better understanding of (I think) the
SwitchStore
andReducer.ifCaseLet
. Of course, I am wide open to suggestions such as, "Here's a simpler way to think about it..." 😄So: a family relationship database. At the top level, we select which extended family we want to be working with. Having selected a family, we have drilled down to a screen that shows all the family members. We can select a particular person and that drills down to a person editing screen, where we can change details for that person. Of particular concern here, we can press a button to add a parent, press a different button to add a partner, or press a third button to add a child. Pressing any of these buttons should pull up a control which lists all the people in the family; selecting a person will return the selected person back to the edit person feature, adding the person to the appropriate list (parents, partners, children).
Now, I have successfully implemented this in a particularly non-TCA way, using a bunch of booleans. However, that's gross -- this definitely feels like a job for enum state, since only one of these picker controls should be visible and active at a time.
So, what should the edit person reducer look like? If I tack an
.ifLet
onto the end, then I have this problem where I have to figure out which picker has generated the action. I think.Beta Was this translation helpful? Give feedback.
All reactions