Currently, pullback takes a WritableKeyPath
as its state
argument. This does not work well with enum state as illustrated in the following example:
enum Content {
case group(Group)
case item(Item)
}
enum ContentAction {
case group(GroupAction)
case item(ItemAction)
}
let contentReducer = Reducer<RequestCollection.Content, ContentAction, Void>.combine(
groupReducer.pullback(state: \Content.group, action: /ContentAction.group, environment: { $0 }),
requestReducer.pullback(state: \Content.request, action: /ContentAction.request, environment: { $0 })
)
This contentReducer
won't compile as WritableKeyPath
s are not automatically generated for enum cases. To work around this issue one could write get/set
properties for each enum case manually:
extension Content {
var group: Group? {
get {
guard case let .group(group) = self else { return nil }
return group
} set {
guard let group = newValue else { return }
self = .group(group)
}
}
// request property left out for brevity
}
As you can see, this property has to be Optional
in "case" the Content
is not a Group
. This means that the pullback would actually have to use the .optional
groupReducer
and .optional
requestReducer
:
let contentReducer = Reducer<RequestCollection.Content, ContentAction, Void>.combine(
groupReducer.optional.pullback(state: \Content.group, action: /ContentAction.group, environment: { $0 }),
requestReducer.optional.pullback(state: \Content.request, action: /ContentAction.request, environment: { $0 })
)
However, in the Composable Architecture this has already been solved with the help of CasePath
s. I believe there should be an option to pullback local state along a CasePath
as well.