Question regarding bubbling up action for a deep nested state, for example:
Handling user authenticated with state structured like this, app > landing> login > 2FA >
A naive approach in app reducer will be :
case let .landing(.login(.twoFactor(.twoFactorResponse(.success(response))))),
let .landing(.login(.loginResponse(.success(response)))) where !response.twoFactorRequired:
...
Globally handle 401 (unauthorized) response from remote server.
A naive approach will be handling this in every reducer or combine it to bubble it up to app state.
Is there an elegant solution for such scenarios? One way i can think of is using long living effects with notification center and combine it with root/app reducer.
As @grinder81 mentions above we've gone through this exercise for the same reason. We need to handle 401 but also we're showing a toast on errors too. So far, we're able to do this using our own FailableReducer type which returns a failable Effect<Action, Error>. We then implemented (copied) the combine, pullback, etc. functions to make everything work. So all the real reducers are FailableReducer.
At the root of the tree, we have a higher-order reducer which does the catch and performs the error handling. This higher-order reducer is the normal non-failable Reducer which can be passed into the Store:
One thing we've been wondering about is if it can make sense for Reducer to return failable Effect<Action, Error> instead of the non-failing Effect<Action, Never>. We tried on this branch and it seems to work out ok so far, but we're looking for feedback on it. We believe there might be a reason for this - whether it's technical or practical though we're not sure. Hoping it can be possible though as it seems it would make this a bit easier for centralized error handling.
By the way, the other approach we dabbled with was have the reducers return Effect<Result<Action, Error>, Never>. It didn't seem straightforward though so we gave up on it rather early.