Last active
February 19, 2019 19:04
-
-
Save ccnokes/9860591e48f05f4f8cd1ea1458e22354 to your computer and use it in GitHub Desktop.
withNgService HOC for injecting modules from Angular.JS's dependency injector into a React component
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
import * as React from 'react'; | |
import hoistStatics from 'hoist-non-react-statics'; | |
declare var angular: any; | |
let injector; | |
// NOTE you probably can't run this at the top level of a module because angular takes time to load and bootstrap | |
export default function getNgService<T = any>(serviceName: string): T { | |
if (!injector) { | |
injector = angular.element(document.body).injector(); | |
// if we still don't get it, blow up | |
if (!injector) { | |
throw new Error(`Unable to get the angular injector`); | |
} | |
} | |
return injector.get(serviceName); | |
} | |
export const withNgService = function <NgProps = {}, ComponentProps = {}>(...injectorKeys: string[]) { | |
return function<Props = ComponentProps>(Component: React.ComponentType<Props & NgProps>): React.ComponentType<Props> { | |
class withNgServiceWrapper extends React.Component<Props & NgProps> { | |
static displayName = `withNgService(${Component.displayName || Component.name})`; | |
static WrappedComponent = Component; | |
private ngProps = injectorKeys.reduce((aggr, key) => { | |
aggr[key] = getNgService(key); | |
return aggr; | |
}, {} as NgProps); | |
render() { | |
return ( | |
<Component | |
{...this.props} | |
{...this.ngProps} | |
/> | |
); | |
} | |
} | |
return hoistStatics(withNgServiceWrapper, Component); | |
} | |
} | |
// test it out | |
interface MyNgProps { | |
ngThing: string | |
} | |
interface Props { | |
a: number | |
} | |
class _Test extends React.Component<Props & MyNgProps> { | |
render() { | |
const { a, ngThing } = this.props | |
return null | |
} | |
} | |
const Test = withNgService<MyNgProps>('$http')(_Test) | |
const Test2 = withNgService<MyNgProps, Props>('$http')((props) => ( | |
<p>{props.ngThing}{props.a}</p> | |
)) | |
class App extends React.Component { | |
render() { | |
return ( | |
<> | |
<Test a={1} /> | |
<Test2 a={123} /> | |
</> | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment