To make an asynchronous request a middleware is used in this case, it returns an error after a fixed amount of time.
The app state is properly updated the subscriber view controller presents the error.
On the next instance however this subscriber view controller is presented, it finds the error in the state - which is actually the error from the previous request and displays the error message before even the request is fired.
How to go about handling this case in ReSwift/Redux?
Store
let store = Store(
reducer: appReducer,
state: AppState(),
middleware: [requestMiddleware]
)
State
struct AppState: StateType {
var isRequestInProgress = false
var result: Result<Bool, NSError>?
}
Actions
struct RequestAction: Action {}
struct ReceiveAction: Action {}
struct ErrorAction: Action {
let error: NSError
}
Middleware
let requestMiddleware: Middleware<Any> = { dispatch, getState in
return { next in
return { action in
switch action {
case is RequestAction:
DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
store.dispatch(ErrorAction(error: NSError(domain: "", code: -1, userInfo: nil)))
})
default:
break
}
return next(action)
}
}
}
Reducer
func appReducer(action: Action, state: AppState?) -> AppState {
var state = state ?? AppState()
switch action {
case is RequestAction:
state.isRequestInProgress = true
case let action as ErrorAction:
state.isRequestInProgress = false
state.result = .failure(action.error)
default: break
}
return state
}
The app
class ViewController: UIViewController {
@IBAction func presentControllerB(_ sender: Any) {
guard let viewController = storyboard?.instantiateViewController(withIdentifier: "ViewControllerB") else {
return
}
present(viewController, animated: true)
}
}
class ViewControllerB: UIViewController, StoreSubscriber {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
store.subscribe(self)
}
override func viewWillDisappear(_ animated: Bool) {
store.unsubscribe(self)
super.viewWillDisappear(animated)
}
func newState(state: AppState) {
showActivity(state.isRequestInProgress)
switch state.result {
case .none:
break
case .some(.success(_)):
break
case .some(.failure(let error)):
presentError(error)
dismiss(animated: true)
}
}
@IBAction func request(_ sender: Any) {
store.dispatch(RequestAction())
}
private func showActivity(_ show: Bool) {}
private func presentError(_ error: Error) {
print("Error")
}
}