Hi,
I'm trying to learn navigation using TCA, and want to create a macOS app with a sidebar. This is what I want to achieve:
Except with the text replaced with ProjectView()
with the corresponding Blob Jr project.
NavigationView
is deprecated and Apple recommends using NavigationSplitView
for this it looks like.
Here's the code I have so far:
import SwiftUI
import ComposableArchitecture
struct Project: Equatable, Identifiable {
let id: UUID
var name: String
}
struct ProjectsFeature: Reducer {
struct State: Equatable {
var projects: IdentifiedArrayOf<Project> = []
var path = StackState<ProjectFeature.State>()
}
enum Action: Equatable {
case addButtonTapped
case path(StackAction<ProjectFeature.State, ProjectFeature.Action>)
}
var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .addButtonTapped:
// TODO: Handle action
return .none
case .path:
return .none
}
}
.forEach(\.path, action: /Action.path) {
ProjectFeature()
}
}
}
struct ProjectsView: View {
let store: StoreOf<ProjectsFeature>
var body: some View {
NavigationStackStore(self.store.scope(state: \.path, action: { .path($0) })) {
WithViewStore(self.store, observe: \.projects) { viewStore in
NavigationSplitView {
List {
ForEach(viewStore.state) { project in
NavigationLink(state: ProjectFeature.State(project: project)) {
Text(project.name)
}
}
}
} detail: {
Text("How do I get ProjectView() with Blob Jr to show here?")
}
}
} destination: { store in
ProjectView(store: store)
}
}
}
ProjectFeature
is just like this:
But I wan't to be able to mutate the project from this view in the future.
struct ProjectFeature: Reducer {
struct State: Equatable {
var project: Project
}
enum Action {
case didUpdateNameTextField
}
func reduce(into state: inout State, action: Action) -> Effect<Action> {
switch(action) {
case .didUpdateNameTextField:
return .none
}
}
}
struct ProjectView: View {
let store: StoreOf<ProjectFeature>
var body: some View {
WithViewStore(self.store, observe: { $0 }) { viewStore in
VStack {
Text("Project").font(.largeTitle)
Text(viewStore.state.project.name)
}
}
}
}
If I remove the NavigationSplitView
, the navigation works, but the display is incorrect.
How can I use this NavigationSplitView
with TCA?