Skip to content

Instantly share code, notes, and snippets.

@jasononeil
Last active October 5, 2021 00:02
Show Gist options
  • Save jasononeil/e835aeb2ce7b9f099616ef2098caac1d to your computer and use it in GitHub Desktop.
Save jasononeil/e835aeb2ce7b9f099616ef2098caac1d to your computer and use it in GitHub Desktop.
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