Using angular dependency injection with react, redux, and redux-thunk
var thunkDispatcherRef = { | |
dispatch: function () {} | |
} | |
/** | |
* The angular injection middleware allows our redux actions to return functions. | |
* | |
* The function will be executed with regular angular dependency injection, allowing | |
* you to use angular services in Redux actions. | |
* | |
* The redux-thunk also operates on actions that return functions. We interact with | |
* thunk by: 1) Adding a provider for the `dispatch` function used by thunk. 2) Carefully | |
* checking the arguments, and if a `dispatch` argument exists, passing redux-thunk a | |
* function that will correctly execute the angular function with the new dispatch funcion. | |
*/ | |
function angularInjectionMiddleware($injector) { | |
return store => next => action => { | |
if (typeof action === 'function') { | |
let injectionsRequired = $injector.annotate(action); | |
if (injectionsRequired.indexOf('dispatch') > -1) { | |
if (injectionsRequired.length === 1) { | |
// Only a dispatch action, pass directly on to redux-thunk. | |
next(action); | |
} else { | |
// We need to run `next`, which will be with redux-thunk. | |
// This will give us the dispatch method, which we can then use in angular injection. | |
let actionForThunk = function (dispatch) { | |
thunkDispatcherRef.dispatch = dispatch; | |
return $injector.invoke(action); | |
} | |
return next(actionForThunk) | |
} | |
} else { | |
// Angular action only, with no `dispatch` argument, so we can return a value and ignore thunk. | |
return next($injector.invoke(action)); | |
} | |
} else { | |
return next(action); | |
} | |
} | |
} | |
angular.module('myApp').factory('dispatch', function () { | |
return thunkDispatcherRef.dispatch; | |
}); | |
angular.module('myApp').factory('angularInjectionMiddleware', angularInjectionMiddleware); | |
export default angularInjectionMiddleware; |
// 3rd party imports | |
import thunkMiddleware from 'redux-thunk'; | |
import createLogger from 'redux-logger'; | |
import {combineReducers} from 'redux'; | |
import ngRedux from 'ng-redux'; // Used by angular, and injected below. | |
import ngReact from 'ngreact'; // Used only by angular. | |
// Middleware | |
import angularInjectionMiddleware from './common/middleware/angularInjectionMiddleware.jsx'; // Injected below. | |
const loggerMiddleware = createLogger(); | |
angular.module('myApp').config(['$ngReduxProvider', function ($ngReduxProvider) { | |
let reducer = combineReducers({ | |
// Your reducers here... | |
}); | |
let middleware = [loggerMiddleware, 'angularInjectionMiddleware', thunkMiddleware]; | |
let storeEnhancers = []; | |
if (window.devToolsExtension) { | |
// Add redux devTools helper if the browser extension is present. | |
storeEnhancers.push(window.devToolsExtension()); | |
} | |
let initialState = {}; | |
$ngReduxProvider.createStoreWith(reducer, middleware, storeEnhancers, initialState); | |
}]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment