I am trying to learn how to do middleware, but I cannot see any good resources to learn from.
I checked:
Can someone help?
Maybe you could be the one missing contributor to a Middleware guide? :) I'd be happy to help.
To get started, creating a simple Middleware with the nested closures looks like this:
import Foundation
import ReSwift
let loggingMiddleware: Middleware<AppState> = { dispatch, getState in
return { next in
return { action in
print("> \(action)")
next(action)
}
}
}
You need to call next(action) to pass the action on to the next object in the chain -- that'd be another Middleware, or in case of the last Middleware, it'd be the main reducer. In other words, if you do not call next(action), you can swallow or filter actions in Middlewares.
dispatch from within a Middleware, the whole ReSwift store dispatching will be executed and finished _before the next line in the Middleware is reached_ since ReSwift works synchronously. That means you can react to incoming actions (think: triggers) in Middleware by dispatching a whole chain of new actions; and you can do so before the trigger itself is reduced to a state update, or after.let bananaMiddleware: Middleware<AppState> = { dispatch, getState in
return { next in
return { action in
guard let bananaAction = action as? BananaAction else {
// Do not react to any other action in any special way:
next(action)
return
}
dispatch(bananaAction.someSideEffectOrServerRequest) // perhaps an ActionCreator
dispatch(ActionBeforeBananaActionIsReduced())
next(action)
dispatch(ActionAfterBananaActionIsReduced())
}
}
}
For this topic, I made simple tools and I called it ReSwiftMiddleware.
A simple example of how to use this
import Foundation
import ReSwift
struct MiddlewareLogger : MiddlewareExecutor{
let logger:LogConsole;
init(logger:LogConsole) {
self.logger = logger;
}
func execute(action: Action, state: StateType?) -> Action? {
if let counterAction = action as? CounterActions{
self.logger.register(value: counterAction.toString())
}
return action
}
}
If you need to interrupt the flow, you return nil on execute method.
The example of implementing MiddlewaresCollection.
let middlewaresCollection = MiddlewaresCollection<CounterState>();
let middlewareLogger = MiddlewareLogger(logger: logger);
middlewaresCollection.add(middlewareLogger);
Now an example of how to connect this collection to [ReSwfit]
let store = Store<CounterState>(reducer: reducerCounterState, state: CounterState(), middleware: middlewaresCollection.middlewares)
Hi, @Tavernari.
Note that this would have some limitations compared to “normal” ReSwift middleware functions, maybe you want to add them in the README:
execute function, that might be obsolete when you use it.Sent with GitHawk
Hi, @Tavernari.
Note that this would have some limitations compared to “normal” ReSwift middleware functions, maybe you want to add them in the README:
- It’s not possible to get the current state after an effect has been run. You only have access to the previous state passed to the
executefunction, that might be obsolete when you use it.- It’s not possible to dispatch new actions, only pass the current one through or skip it.
- It’s not possible to apply a side effect after the action has continued with the middleware chain (potentially having reached the reducers).
Sent with GitHawk
Hi @danielmartinprieto,
Thanks for the observations, I made some updates on version 0.1.2 and now I think it's not more obsolete and you can dispatch action direct from inside the MiddlewareExecutor.
struct MiddlewareLogger : MiddlewareExecutor{
let logger:LogConsole;
init(logger:LogConsole) {
self.logger = logger;
}
func execute(action: Action, getState: @escaping () -> StateType?, dispatch: @escaping DispatchFunction) -> Action? {
if let counterAction = action as? CounterActions{
self.logger.register(value: counterAction.toString())
}
return action
}
}
@Tavernari I was extremely confused with ReSwiftMiddleware because it's just a function which makes it not easy to use dependency injection for testing purposes. I am using your MiddlewareExecutor and it helped me greatly to both understand the general concept and with my testing.
@atacengiz My idea on this framework is to help developers to use Middlewares, if you look the syntax with many functions inside functions, for me is not clear and demand more knowledge about swift syntax, so ReSwiftMiddleware helps developers to implement Middlewares easily using objects.
I hope to help many others to use ReSwift because I really love this framework.
Most helpful comment
Maybe you could be the one missing contributor to a Middleware guide? :) I'd be happy to help.
Creation
To get started, creating a simple Middleware with the nested closures looks like this:
Basics
You need to call
next(action)to pass the action on to the next object in the chain -- that'd be another Middleware, or in case of the last Middleware, it'd be the main reducer. In other words, if you do not callnext(action), you can swallow or filter actions in Middlewares.dispatchfrom within a Middleware, the whole ReSwift store dispatching will be executed and finished _before the next line in the Middleware is reached_ since ReSwift works synchronously. That means you can react to incoming actions (think: triggers) in Middleware by dispatching a whole chain of new actions; and you can do so before the trigger itself is reduced to a state update, or after.