Hey everyone, got a unique TCA issue I'm trying to figure out. Working a dynamic form builder project and trying to figure out how to have two reducers that depend on each other. Below is a simplified example of what I'm trying to accomplish:
struct Form {
var rootSection: SectionDefinition
}
struct SectionDefinition {
var units: IdentifiedArrayOf<UnitDefinition>
}
enum UnitDefinition: Equatable {
case section(SectionDefinition)
case field(FieldDefinition)
}
This is my basic data model; a Form
has a root section SectionDefinition
and a section definition has a list of UnitDefinition
enums. One of those unit types is also a section, since they can be nested. Trying to figure out how to set up my reducers to make it work:
typealias FormReducer = Reducer<Form, FormAction, FormEnvironment>
let formReducer: FormReducer = .combine(
sectionReducer
.pullback(
state: \.rootSection,
action: /FormAction.rootSection,
environment: { $0.rootSection }
)
)
typealias SectionReducer = Reducer<SectionDefinition, SectionAction, SectionEnvironment>
let sectionReducer: SectionReducer = .combine(
unitReducer.forEach(
state: \.units,
action: /SectionAction.unit(id:action:),
environment: { $0.unit }
)
)
typealias UnitReducer = Reducer<UnitDefinition, UnitAction, UnitEnvironment>
let unitReducer: UnitReducer = .combine(
sectionReducer
.pullback(
state: /UnitDefinition.section,
action: /UnitAction.section,
environment: { $0.section }
),
fieldReducer
.pullback(
state: /UnitDefinition.field,
action: /UnitAction.field,
environment: { $0.field }
)
)
The formReducer
does a pullback on the root section using the section reducer, the section reducer does a forEach over the units using the unitReducer, but then the unit reducer also needs to do a pullback on the section reducer. This compiles fine but crashes at runtime. If I remove the sectionReducer.pullback
from the unitReducer
things mostly work, except for supporting nested sections.
Are there any tricks or tips for making this work?
Thanks in advance!