Last active
December 9, 2015 19:15
-
-
Save bradharms/03827796ebf6799130ef to your computer and use it in GitHub Desktop.
Allows Redux action creators to use a limited form of dependency injection.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Allows Redux action creators to use a limited form of dependency injection. | |
* | |
* To apply: | |
* | |
* import { applyMiddleware, createStore } from 'redux'; | |
* import inject from './redux-inject'; | |
* | |
* import dep1 from '.../dep1'; | |
* import dep2 from '.../dep2'; | |
* | |
* const createStoreWithMiddleware = applyMiddleware( | |
* // Note that inject() is a 'curried' function | |
* inject({dep1, dep2}); | |
* )(createStore); | |
* | |
* After being applied, all action creators will be able to return a | |
* "dependency wrapper" function which will be given server-side versions of | |
* dependencies by name. The wrapper's return value will be passed to the | |
* next middleware via `next()`. Therefore, the signature of an action creator | |
* for such a function would look like this: | |
* | |
* const createFooAction = (payload) => ({dep1, dep2, ...deps}) => { | |
* // ...use dep1... | |
* // ...use dep2... | |
* return { type: FOO, ...payload }; | |
* } | |
* | |
* Rational: | |
* | |
* This middleware was created to resolve a problem I faced while trying to | |
* write isomorphic model access code. My action creators needed to be used on | |
* both the client and the server, but they needed to access model data in | |
* different ways depending on which end they were currently running on. I | |
* decided the best way to do this was to provide the model access code via | |
* dependency injection, and the only way I could think to do it was using a | |
* redux middleware. | |
* | |
* Notes: | |
* | |
* This was intended to be used in conjunction with redux-thunk. When the two | |
* are used together, you must be careful to ensure that the action creators | |
* nest their functions in the correct order. This order will be the | |
* same order in which the middlewares are applied, as in this example: | |
* | |
* // --- configureStore.js --- | |
* const createStoreWithMiddleware = applyMiddleware( | |
* inject({dep1, dep2}), | |
* thunk | |
* )(createStore); | |
* | |
* // --- actions.js --- | |
* | |
* // RIGHT: | |
* const createFooAction = (payload) => (deps) => (dispatch) => { | |
* return dispatch | |
* } | |
* | |
* // WRONG: dispatch will receive the deps, and the deps will receive the | |
* // dispatch function. | |
* const createFooAction = (payload) => (dispatch) => (deps) => { ... } | |
* | |
* TODO: Don't depend on any third-party libraries (ie. lodash) | |
* TODO: Don't use ES6 syntax in definition | |
* TODO: Export as a stand-alone middleware from Github | |
*/ | |
import _ from 'lodash'; | |
export default deps => () => next => action => | |
next(_.isFunction(action) ? action(deps) : action); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment