react2angular
react2angular copied to clipboard
How to inject angularjs dependencies in child react components?
Let's say I use this library to attach a react component to a route /users
.
import { react2angular } from 'react2angular';
import EditContractContainer from './EditContractContainer.jsx';
import EpisodeEditorApiMod from '../../yamsf/episode-editor';
import PayorApiMod from '../../yamsf/payer-service';
var angular = require('angular');
module.exports = angular.module('mymod.edit', [
EpisodeEditorApiMod, PayorApiMod
])
.component('editContractContainer', react2angular(EditContractContainer, [], ['$injector']))
.config(function($stateProvider) {
$stateProvider.state({
name: 'EditContractContainer',
url: '/edit-contract/:contractId',
component: 'editContractContainer'
});
})
.name;
And then Then that react component has it's own child components. How do those child components get access to angularjs services?
I ran into this so I came up w/ the idea to inject $injector
into my parent component. Then I pass it down as props to the children. Then they can use this to pick of any angularjs services they need.
this.$stateParams = $injector.get('$stateParams');
this.contractService = $injector.get('contractService');
But there's a catch.. You can only inject providers which have been added as dependencies to the parent module. So that means if a downstream component wants to $inject
userService
, I'd have to go back up to the parent module where the react2angular
component is added, and add:
import UserAPIMod from '../../yamsf/user-service';
And then add it as a requirement
module.exports = angular.module('mymod.edit', [
EpisodeEditorApiMod, PayorApiMod, UserAPIMod
])
Is there a way around this? I really don't like it because then components have requirements on their parents. Also it's undoubtedly going to get to the point where that parent module is including a bunch of stuff its children no longer use. How would you combat this?
Hi there! If you are comfortable with using something a bit stateful, and not varying injectors by component tree, you can do this with:
const myService = angular.element(document.body).injector().get(SERVICE_NAME);
You can even write a hook to cache this. Something like:
function useAngularInjection(name) {
return useMemo(() => angular.element(document.body).injector().get(name), [])
}
function MyComponent(props) {
const stateParams = useAngularInjection('$stateParams');
return <> ... </>;
}