Last active
October 5, 2021 00:02
-
-
Save jasononeil/e835aeb2ce7b9f099616ef2098caac1d to your computer and use it in GitHub Desktop.
Using angular dependency injection with react, redux, and redux-thunk
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
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; |
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
// 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