Inject props to your react component.
npm i react inversify react-inject-props --save
or
yarn add react inversify react-inject-props
with typescript, you should install the "reflect-metadata" package as well:
npm i reflect-metadata --save or yarn add reflect-metadata
- get decorators
- inject
- hierarchical injection
- useExisting
- get container from props
- use ContainerContext directly
you can create decorators InjectProps and ProvideProps use createPropsDecorators function with a inversify container instance as the root container:
import { Container } from 'inversify';
import { createPropsDecorators } from 'react-inject-props';
const container = new Container();
const {InjectProps, ProvideProps, containerManager} = createPropsDecorators(container);if rootContainer not specified, createPropsDecorators will create it internally, you can take it from the function result:
import { createPropsDecorators } from 'react-inject-props';
const {InjectProps, ProvideProps, containerManager} = createPropsDecorators();
const rootContainer = containerManager.rootNode.container;import { injectable } from 'inversify';
import React from 'react';
import { render } from 'react-dom';
@injectable()
class Service {
greeting () {
console.log('hello world');
}
}
// or simply
// @ProvideProps([
// Service
// ])
@ProvideProps([
{provide: Service, useClass: Service}
])
export class App extends React.Component {
render () {
return ...;
}
}
interface PageProps {
service?: Service;
}
@InjectProps({
service: Service
})
export class Page extends React.Component<PageProps> {
componentDidMount () {
this.props.service!.greeting();
}
...
}
render((
<App>
<Page/>
</App>
), document.getElementById('root'));in Page component, we can access Service instance by this.props.service, because we bind Service to container at App component with ProvideProps decorator and "Inject" it as this.props.service by InjectProps.
interface AppConfig {
siteName: string;
}
const AppConfigToken = Symbol('appConfig');
const appConfig: AppConfig = {
siteName: 'Github'
};
@ProvideProps([
{provide: AppConfigToken, useValue: appConfig}
])
export class App extends React.Component {
}
interface PageProps {
appConfig?: AppConfig
}
@InjectProps({
appConfig: AppConfigToken
})
export class Page extends React.Component<PageProps> {
componentDidMount () {
console.log(this.props.appConfig!.siteName);
}
}@injectable()
class Service {
getConfig () {
return {
siteName: 'Github'
};
}
}
const AppConfigToken = Symbol('appConfig');
function getAppConfig (service: Service) {
return service.getConfig();
}
@ProvideProps([
Service,
{provide: AppConfigToken, useFactory: getAppConfig, deps: [Service]}
])
export class App extends React.Component {
}
interface PageProps {
appConfig?: AppConfig
}
@InjectProps({
appConfig: AppConfigToken
})
export class Page extends React.Component<PageProps> {
componentDidMount () {
console.log(this.props.appConfig!.siteName);
}
}we can use multiple ProvideProps decorators in different hierarchies to implement an hierarchical injection system.
@injectable()
class Service {
id = Math.random();
}
@ProvideProps([
Service
])
class App extends React.Component {}
@InjectProps({
service: Service
})
class PageA extends React.Component {}
@InjectProps({
service: Service
})
class CompInPageA extends React.Component {}
@ProvideProps([
Service
])
@InjectProps({
service: Service
})
class PageB extends React.Component {}
render((
<App>
<PageA>
<CompInPageA/>
</PageA>
<PageB/>
</App>
), ...);in the above example, PageA.props.service is equals to CompInPageA.props.service and difference to PageB.props.service, case PageB is reprovide a Service.
@ProvideProps([
{provide: Service, useClass: Service, useExisting: true}
])
class Comp extends React.Component { }
render ((
<App>
<Comp/>
</App>
), ...);if Service can be resolved in App's providers or rootContainer, the Service provider will be ignored.
import { Container } from 'inversify';
interface CompProps {
container: Container;
}
@ProvideProps([
Service
])
class Comp extends React.Component<CompProps> {
componentDidMount () {
const {container} = this.props;
...
}
}container of current component's hierarchy will also inject in component.props when use ProvideProps or InjectProps decorator.
import { ContainerContext } from 'react-inject-props';
// or
import { createPropsDecorators } from 'react-inject-props';
const {ContainerContext} = createPropsDecorators();
// then use it in your component
class Comp extends React.Component {
render () {
return (
<ContainerContext.Provider value={xxx}>
...
...
<ContainerContext.Consumer>
{(container: Container) => {
...
}}
</ContainerContext.Consumer>
...
...
</ContainerContext.Provider>
);
}
}