Replies: 2 comments
-
aha, the answer occurred to me today 🦆 Here we use an enum for the possible child states, but keep the actions directly in the parent domain. The asymmetry threw me, but now I see why the struct ParentCaseStateState: Equatable {
var route: Children?
}
enum Children: Equatable {
case child1(Child1State)
case child2(Child2State)
}
enum ParentCaseStateAction: Equatable {
case child1(PresentationAction<Child1Action>)
case child2(PresentationAction<Child2Action>)
}
let ParentCaseStateReducer = Reducer<ParentCaseStateState, ParentCaseStateAction, Void>.combine(
Reducer { state, action, environment in
switch action {
case .child1(.present):
state.route = .child1(.init())
return .none
case .child1(.dismiss):
state.route = nil
return .none
case .child1:
return .none
case .child2(.present):
state.route = .child2(.init())
return .none
case .child2(.dismiss):
state.route = nil
return .none
case .child2:
return .none
}
}
.presents(
destination: Child1Reducer,
unwrapping: \.route,
case: /Children.child1,
action: /ParentCaseStateAction.child1,
environment: { $0 }
)
.presents(
destination: Child2Reducer,
unwrapping: \.route,
case: /Children.child2,
action: /ParentCaseStateAction.child2,
environment: { $0 }
)
)
struct ParentCaseStateView: View {
let store: Store<ParentCaseStateState, ParentCaseStateAction>
var body: some View {
WithViewStore(store.stateless) { viewStore in
List {
NavigationLinkStore(
unwrapping: store.scope(
state: \.route,
action: ParentCaseStateAction.child1
),
case: /Children.child1
) { navStore in
Child1View(store: navStore)
} label: {
Text("Child 1")
}
NavigationLinkStore(
unwrapping: store.scope(
state: \.route,
action: ParentCaseStateAction.child2
),
case: /Children.child2
) { navStore in
Child2View(store: navStore)
} label: {
Text("Child 2")
}
}
}
}
}
struct ParentCaseState_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
ParentCaseStateView(
store: .init(
initialState: .init(
route: nil
),
reducer: ParentCaseStateReducer,
environment: ()
)
)
}
}
} Here's the new NavigationLinkStore constructor to support this use. extension NavigationLinkStore {
init(
unwrapping store: Store<Enum?, PresentationAction<Action>>,
case casePath: CasePath<Enum, Case>,
@ViewBuilder destination: @escaping (Store<Case, LocalAction>) -> Destination,
@ViewBuilder label: () -> Label
) where Action == LocalAction {
self.store = store
self.destination = destination
self.casePath = casePath
self.toLocalAction = { $0 }
self.label = label()
}
} |
Beta Was this translation helpful? Give feedback.
0 replies
-
Here's a cleaned up struct NavigationLinkStore<Enum, Case, Action, Destination: View, Label: View>: View {
let store: Store<Enum?, PresentationAction<Action>>
let casePath: CasePath<Enum, Case>
let destination: (Store<Case, Action>) -> Destination
let label: Label
init(
unwrapping store: Store<Enum?, PresentationAction<Action>>,
case casePath: CasePath<Enum, Case>,
@ViewBuilder destination: @escaping (Store<Case, Action>) -> Destination,
@ViewBuilder label: () -> Label
) {
self.store = store
self.destination = destination
self.casePath = casePath
self.label = label()
}
init(
unwrapping store: Store<Enum?, PresentationAction<Action>>,
@ViewBuilder destination: @escaping (Store<Case, Action>) -> Destination,
@ViewBuilder label: () -> Label
) where Enum == Case {
self.store = store
self.destination = destination
self.casePath = /.self
self.label = label()
}
var body: some View {
WithViewStore(store.scope(state: { $0.flatMap(casePath.extract(from:)) != nil })) { viewStore in
NavigationLink(isActive: viewStore.binding(send: { $0 ? .present : .dismiss })) {
IfLetStore(
store.scope(
state: self.casePath.cacheExtract,
action: PresentationAction.presented
),
then: self.destination
)
} label: {
self.label
}
}
}
} |
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 was playing with navigation using this gist that @mbrandonw shared recently. Really liking it, and it seems to be the basis for much bigger ideas in the
protocol-navigation
branch?I ran into what's either a data modeling issue or a limitation of of the tools, so wanted to check my thinking:
First I introduced
NavigationLinkStore
as I'm not working with ios16 yet. In looking at the proto branch it seems that the same core issue remains if usingnavigationDestination
Here I model a simple navigation list from parent to one of two children. It works great but it feels like the children should be modeled as an enum?
So here's a version that models the children as a route domain. The problem is, both navigation links sends the same
.present
actions so there's no way to know which state to create.Beta Was this translation helpful? Give feedback.
All reactions