Created
July 11, 2024 19:29
-
-
Save DandyLyons/9d14291284a12939504fc653122167e5 to your computer and use it in GitHub Desktop.
Tree-Based Push onto NavigationStack using TCA
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import SwiftUI | |
| @main | |
| struct TreeBasedPushApp: App { | |
| var body: some Scene { | |
| WindowGroup { | |
| TreeBasedPush_V() | |
| } | |
| } | |
| } | |
| import ComposableArchitecture | |
| @Reducer struct TreeBasedPush_R { | |
| @Reducer enum Destination { | |
| case child1(Child1_R) | |
| case child2(Child2_R) | |
| } | |
| @ObservableState struct State { | |
| @Presents var destination: Destination.State? | |
| } | |
| enum Action { | |
| case destination(PresentationAction<Destination.Action>) | |
| case present(Destination.State) | |
| } | |
| var body: some ReducerOf<Self> { | |
| Reduce { state, action in | |
| switch action { | |
| case .destination: return .none | |
| case let .present(destState): | |
| state.destination = destState | |
| return .none | |
| } | |
| } | |
| .ifLet(\.$destination, action: \.destination) | |
| } | |
| } | |
| struct TreeBasedPush_V: View { | |
| @Bindable var store: StoreOf<TreeBasedPush_R> = .init( | |
| initialState: .init(), | |
| reducer: { TreeBasedPush_R()._printChanges() } | |
| ) | |
| var body: some View { | |
| NavigationStack { | |
| List { | |
| Button("Child 1") { store.send(.present(.child1(.init())))} | |
| Button("Child 2") { store.send(.present(.child2(.init())))} | |
| } | |
| .navigationTitle("root") | |
| .navigationDestination( | |
| item: $store.scope(state: \.destination?.child1, action: \.destination.child1) | |
| ) { store in | |
| Child1_V(store: store) | |
| } | |
| .navigationDestination( | |
| item: $store.scope(state: \.destination?.child2, action: \.destination.child2) | |
| ) { store in | |
| Child2_V(store: store) | |
| } | |
| } | |
| } | |
| } | |
| @Reducer struct Child1_R { | |
| @Reducer enum Destination { | |
| case child1(Child1_R) | |
| case child2(Child2_R) | |
| } | |
| @ObservableState struct State { | |
| @Presents var destination: Destination.State? | |
| } | |
| enum Action { | |
| case destination(PresentationAction<Destination.Action>) | |
| case present(Destination.State) | |
| } | |
| var body: some ReducerOf<Self> { | |
| Reduce { state, action in | |
| switch action { | |
| case .destination: return .none | |
| case let .present(destState): | |
| state.destination = destState | |
| return .none | |
| } | |
| } | |
| .ifLet(\.$destination, action: \.destination) | |
| } | |
| } | |
| struct Child1_V: View { | |
| @Bindable var store: StoreOf<Child1_R> = .init( | |
| initialState: .init(), | |
| reducer: { Child1_R() } | |
| ) | |
| var body: some View { | |
| List { | |
| Button("Child 1") { store.send(.present(.child1(.init())))} | |
| Button("Child 2") { store.send(.present(.child2(.init())))} | |
| } | |
| .navigationTitle("Child 1") | |
| .navigationDestination( | |
| item: $store.scope(state: \.destination?.child1, action: \.destination.child1) | |
| ) { store in | |
| Child1_V(store: store) | |
| } | |
| .navigationDestination( | |
| item: $store.scope(state: \.destination?.child2, action: \.destination.child2) | |
| ) { store in | |
| Child2_V(store: store) | |
| } | |
| } | |
| } | |
| @Reducer struct Child2_R { | |
| @Reducer enum Destination { | |
| case child1(Child1_R) | |
| case child2(Child2_R) | |
| } | |
| @ObservableState struct State { | |
| @Presents var destination: Destination.State? | |
| } | |
| enum Action { | |
| case destination(PresentationAction<Destination.Action>) | |
| case present(Destination.State) | |
| } | |
| var body: some ReducerOf<Self> { | |
| Reduce { state, action in | |
| switch action { | |
| case .destination: return .none | |
| case let .present(destState): | |
| state.destination = destState | |
| return .none | |
| } | |
| } | |
| .ifLet(\.$destination, action: \.destination) | |
| } | |
| } | |
| struct Child2_V: View { | |
| @Bindable var store: StoreOf<Child2_R> = .init( | |
| initialState: .init(), | |
| reducer: { Child2_R() } | |
| ) | |
| var body: some View { | |
| List { | |
| Button("Child 1") { store.send(.present(.child1(.init())))} | |
| Button("Child 2") { store.send(.present(.child2(.init())))} | |
| } | |
| .navigationTitle("Child 2") | |
| .navigationDestination( | |
| item: $store.scope(state: \.destination?.child1, action: \.destination.child1) | |
| ) { store in | |
| Child1_V(store: store) | |
| } | |
| .navigationDestination( | |
| item: $store.scope(state: \.destination?.child2, action: \.destination.child2) | |
| ) { store in | |
| Child2_V(store: store) | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment