Skip to content

"enhancer" is actually a middleware, not an enhancer #24

@hedgepigdaniel

Description

@hedgepigdaniel

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), and next (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 enhancer argument to Store.create be 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 applyMiddleware function, 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);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions