In my work I've found that if I'm working with external dependencies that return effects, that I need to receive values on the main queue before making UI updates. However if I do that, I often need to re-erase to an effect (for example):
let reducer = MyReducer { state, action, env in
switch action {
case .onAppear:
return env.api
.loadData()
.map(.dataLoaded)
.receive(on: env.mainScheduler)
.eraseToEffect()
case .dataLoaded(let data):
state.data = data
return .none
}
In this case, if loadData returned an Effect, it wouldn't matter since there's no receive(on:) overload on Effect, which means the return value is just a publisher that needs to be erased again. If Effect had a custom receive(on:) overload that specified an Effect as a return value, I could take advantage of dependencies that return effects and make my reducer code a little bit less verbose by omitting eraseToEffect calls in more places.
Is this something that would be useful or wanted in TCA itself?
1 Like
clayellis
(Clay Ellis)
2
So the motivation is essentially just to remove the need to eraseToEffect at the end? I don't think that would pass the bar to be included in the core framework — it isn't necessary for composition. That's just my opinion, though.
Definitely an interesting idea! We already overload map, so overloading receive(on:) could be worth it, given how often it's done. Let's start thinking about it.
2 Likes
jagreenwood
(Jeremy Greenwood)
4
Alternatively, could you pass your scheduler in to loadData() such that the returned Effect is on main?
Passing a scheduler into loadData is possible, but that seems like it'd just be reinventing receive(on:) in a less-extensible or reusable way. I'd still have to erase to effect inside the implementation of the loadData method, and i guess from a more ideological viewpoint, it seems superfluous, since you may not want to force the api consumer to choose a scheduler to run things on when you call loadData, since it's pretty well known you can call receive(on:) at any point in a combine operator chain.