Should side effects always run as an Effect in a reducer? #2038
-
Say I have a simple reducer struct Button: ReducerProtocol {
struct State { var isTapped: Bool = false }
enum Action { case tap }
func reduce(into state: inout State, action: Action) -> EffectTask<Action> {
switch action {
case .tap:
state.isTapped = true
return .none
}
}
} I wanted to adding logging capability to the tap action, I could add a new environment variable for it struct Button: ReducerProtocol {
var trackClosure: () -> Void
func reduce(into state: inout State, action: Action) -> EffectTask<Action> {
switch action {
case .tap:
state.isTapped = true
// Option 1: Call it directly
trackClosure()
// Option 2: Return as an effect
return .fireAndForget(trackClosure)
}
}
} Are there any differences between option 1 and 2? is there a preference between them? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
Hey @superx3man! There are a few dependencies that are deemed acceptable to be called inline. Mostly sync dependencies that are not producing side-effects, like |
Beta Was this translation helpful? Give feedback.
-
IMO the practical approach is to not worry about putting logs into effects unless you happen to be logging the behaviour of an effect itself. I would only make this exception for logging. I will put logs into effects where practical but I’m not a purist about it. |
Beta Was this translation helpful? Give feedback.
Hey @superx3man!
This is different, because the first option makes the function "impure" in the functional sense.
It means that the overall state of the system may be different when passing the same
state
andaction
to the reducer. This is not really problematic nowadays becauseEffect
s are always run at some point, but we can imagine a kind ofTry
higher order reducer where it would perform the reduction and potentially discard/revert the changes ifstate
ends up in some specific state. But in this case, the logging that you performed inline wouldn't be reverted and will appear in your logs, whereas theEffect
will simply not be executed in the second case. This is hypothetical, and righ…