Ok I'm sorry, I should be more specific on my example, here is updated code, hopefully it is more clarified.
Here is a TestFeature.swift:
struct TestWrapper: Equatable, Identifiable {
var test: String
let id: UUID
}
struct DetailWrapper: Equatable, Identifiable {
var name: String
let id: UUID
}
struct TestFeature : ReducerProtocol {
struct State: Equatable {
var loading: Bool = false
var selection: Identified<TestWrapper.ID, BigFeature.State?>?
var tests: IdentifiedArrayOf<TestWrapper> = []
}
enum Action: Equatable {
case onAppear
case onDisapper
case setShowingBigFeature(selection: UUID?)
case bigFeature(BigFeature.Action)
}
var body: some ReducerProtocol<State, Action> {
Reduce { state, action in
switch action {
case .onAppear:
// init data to tests
return .none
case let .setShowingBigFeature(selection: .some(id)):
state.selection = Identified(BigFeature.State(), id: id)
return .none
case .setShowingBigFeature(selection: .none):
state.selection = nil
return .none
default: return .none
}
}
.ifLet(\.selection, action: /Action.bigFeature){
EmptyReducer()
.ifLet(\Identified<TestWrapper.ID, BigFeature.State?>.value, action: .self){
BigFeature()
}
}
}
}
struct TestView: View {
let store: StoreOf<TestFeature>
var body: some View {
WithViewStore(self.store, observe: { $0 }) { viewStore in
NavigationView {
Text("TestView")
LazyVGrid(columns: Array(repeating: GridItem(.flexible(), spacing: 2), count: 2), spacing: 2) {
ForEach(viewStore.tests) { test in
NavigationLink(
destination: IfLetStore(
self.store.scope(
state: \.selection?.value,
action: TestFeature.Action.bigFeature
)
) {
BigFeatureView(store: $0)
} else: {
ProgressView()
},
tag: test.id,
selection: viewStore.binding(
get: \.selection?.id,
send: TestFeature.Action.setShowingBigFeature(selection:)
)
) {
Text("test \(test)")
}
}
}
}
}
}
}
Then here is "BigFeature":
struct BigFeature : ReducerProtocol {
struct State: Equatable {
var loading: Bool = false
var selection: Identified<DetailWrapper.ID, DetailFeature.State?>?
var bigFeatureTests: IdentifiedArrayOf<DetailWrapper> = []
}
enum Action: Equatable {
case onAppear
case onDisapper
case setShowingDetailFeature(selection: UUID?)
case detailFeature(DetailFeature.Action)
}
var body: some ReducerProtocol<State, Action> {
Reduce { state, action in
switch action {
case .onAppear:
// init data to bigFeatureTests
return .none
case let .setShowingDetailFeature(selection: .some(id)):
state.selection = Identified(DetailFeature.State(), id: id)
return .none
case .setShowingDetailFeature(selection: .none):
state.selection = nil
return .none
default: return .none
}
}
.ifLet(\.selection, action: /Action.detailFeature){
EmptyReducer()
.ifLet(\Identified<DetailWrapper.ID, DetailFeature.State?>.value, action: .self){
DetailFeature()
}
}
}
}
struct BigFeatureView: View {
let store: StoreOf<BigFeature>
var body: some View {
WithViewStore(self.store, observe: { $0 }) { viewStore in
NavigationView {
Text("BigFeatureView")
LazyVGrid(columns: Array(repeating: GridItem(.flexible(), spacing: 2), count: 1), spacing: 2) {
ForEach(viewStore.bigFeatureTests) { test in
NavigationLink(
destination: IfLetStore(
self.store.scope(
state: \.selection?.value,
action: BigFeature.Action.detailFeature
)
) {
DetailFeatureView(store: $0)
} else: {
ProgressView()
},
tag: test.id,
selection: viewStore.binding(
get: \.selection?.id,
send: BigFeature.Action.setShowingDetailFeature(selection:)
)
) {
Text("Big feature \(test)")
}
}
}
}
}
}
}
And finally DetailFeature which should navigate on "BigDetail but with another data":
struct DetailFeature : ReducerProtocol {
struct State: Equatable {
var loading: Bool = false
var selection: Identified<TestWrapper.ID, BigFeature.State?>?
var detailTests: IdentifiedArrayOf<TestWrapper> = []
}
indirect enum Action: Equatable {
case onAppear
case onDisapper
case setShowingBigFeature(selection: UUID?)
case bigFeature(BigFeature.Action)
}
var body: some ReducerProtocol<State, Action> {
Reduce { state, action in
switch action {
case .onAppear:
// init data to detailTests
return .none
case let .setShowingBigFeature(selection: .some(id)):
state.selection = Identified(BigFeature.State(), id: id)
return .none
case .setShowingBigFeature(selection: .none):
state.selection = nil
return .none
default: return .none
}
}
.ifLet(\.selection, action: /Action.bigFeature){
EmptyReducer()
.ifLet(\Identified<TestWrapper.ID, BigFeature.State?>.value, action: .self){
BigFeature()
}
}
}
}
struct DetailFeatureView: View {
let store: StoreOf<DetailFeature>
var body: some View {
WithViewStore(self.store, observe: { $0 }) { viewStore in
NavigationView {
Text("DetailFeatureView")
LazyVGrid(columns: Array(repeating: GridItem(.flexible(), spacing: 2), count: 1), spacing: 2) {
ForEach(viewStore.detailTests) { test in
NavigationLink(
destination: IfLetStore(
self.store.scope(
state: \.selection?.value,
action: DetailFeature.Action.bigFeature
)
) {
BigFeatureView(store: $0)
} else: {
ProgressView()
},
tag: test.id,
selection: viewStore.binding(
get: \.selection?.id,
send: DetailFeature.Action.setShowingBigFeature(selection:)
)
) {
Text("Detail feature \(test)")
}
}
}
}
}
}
}
Maybe I am doing it wrong, and I have some misunderstanding, but is there any way how can I do it?
Many Thanks ! :)