-
Notifications
You must be signed in to change notification settings - Fork 40
Description
I think there is a misunderstanding in Reductive about what a Redux enhancer is. From the redux docs:
- A middleware is a function from
getState(returns the current state of the store),dispatch(dispatches an action to the store), andnext(dispatches an action to the next middleware in the chain). A middleware intercepts actions dispatched to the store and can block, change, or delay them or dispatch other actions as a result. - An enhancer is a function that composes a storeCreator to return a new storeCreator. Enhancers wrap the entire API of the store.
Everything that a middleware can do can be done by an enhancer (as evidenced by the fact that the applyMiddlewares function from redux returns an enhancer), but the opposite is not true! Some things that enhancers can do that middlewares cannot:
- Change the initial state of the store without dispatching any actions.
- Change the reducer before the store is created
- Dispatch actions in response to external events (e.g. navigation actions), without waiting for any other actions to be dispatched first.
A middleware cannot do these things because it is only called when an action is dispatched to the store. An enhancer wraps the storeCreator, so it can change the state before the store is created and dispatch actions before other actions are dispatched.
I propose the following alternative:
- The
enhancerargument toStore.createbe removed - The docs be updated to say that an enhancer is a function from a storeCreator to a storeCreator (many of which can be composed into another store enhancer)
- An
applyMiddlewarefunction, that returns an enhancer that applies the (possibly composed) middleware that is passed to it.
This way it is clear how a store enhancer in the Redux sense can be applied, and the user controls the order in which enhancers and middlewares are applied.
Some types:
type store('action, 'state) = Reductive.Store.t('action, 'state);
type dispatch('action, 'state) = store('action, 'state) => 'action => unit;
type getState('action, 'state) = store('action, 'state) => 'state;
type reducer('action, 'state) = 'state => 'action => 'state;
type middleware('action, 'state) = store('action, 'state) => ('action => unit) => 'action => unit;
type storeCreator('action, 'state) = reducer('action, 'state) => 'state => store('action, 'state);
type enhancer('action, 'state) = storeCreator('action, 'state) => storeCreator('action, 'state);
type applyMiddleware('action, 'state) = middleware('action, 'state) => enhancer('action, 'state);